@trymellon/js 1.5.0 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/angular/index.ts","../src/angular/trymellon.service.ts","../src/utils/result.ts","../src/errors.ts","../src/core/validators/helpers.ts","../src/core/validators/register-auth.ts","../src/core/validators/session.ts","../src/core/validators/email.ts","../src/core/validators/onboarding.ts","../src/core/validators/cross-device.ts","../src/core/validators/recovery.ts","../src/core/api.ts","../src/core/fetch-client.ts","../src/utils/support.ts","../src/utils/base64url.ts","../src/utils/validation.ts","../src/core/webauthn-utils.ts","../src/core/webauthn.ts","../src/core/onboarding-manager.ts","../src/core/cross-device-manager.ts","../src/core/events.ts","../src/core/recover.ts","../src/core/constants.ts","../src/core/adapters/telemetry-sender.ts","../src/core/ports/telemetry.ts","../src/core/trymellon.ts"],"sourcesContent":["import type { Provider } from '@angular/core';\nimport type { TryMellonConfig } from '../types';\nimport { TRYMELLON_CONFIG } from './trymellon.service';\n\nexport { TryMellonService, TRYMELLON_CONFIG } from './trymellon.service';\n\nexport function provideTryMellonConfig(config: TryMellonConfig): Provider {\n return { provide: TRYMELLON_CONFIG, useValue: config } as Provider;\n}\n","import { Injectable, InjectionToken, inject } from '@angular/core';\nimport { TryMellon } from '../core/trymellon';\nimport type { TryMellonConfig } from '../types';\n\nexport const TRYMELLON_CONFIG = new InjectionToken<TryMellonConfig>('TRYMELLON_CONFIG');\n\n@Injectable({ providedIn: 'root' })\nexport class TryMellonService {\n private readonly config = inject(TRYMELLON_CONFIG, { optional: true });\n private _client: TryMellon | null = null;\n\n get client(): TryMellon {\n if (this._client == null) {\n if (this.config == null) {\n throw new Error(\n 'TryMellonService: provide TRYMELLON_CONFIG (e.g. via provideTryMellonConfig(config))'\n );\n }\n this._client = new TryMellon(this.config);\n }\n return this._client;\n }\n}\n","export type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\nexport function map<T, E, U>(result: Result<T, E>, mapper: (value: T) => U): Result<U, E> {\n if (result.ok) {\n return ok(mapper(result.value));\n }\n return result;\n}\n\nexport function mapErr<T, E, F>(result: Result<T, E>, mapper: (error: E) => F): Result<T, F> {\n if (!result.ok) {\n return err(mapper(result.error));\n }\n return result;\n}\n\nexport function unwrap<T, E>(result: Result<T, E>): T {\n if (result.ok) {\n return result.value;\n }\n throw result.error;\n}\n","export type TryMellonErrorCode =\n | 'NOT_SUPPORTED'\n | 'USER_CANCELLED'\n | 'PASSKEY_NOT_FOUND'\n | 'SESSION_EXPIRED'\n | 'NETWORK_FAILURE'\n | 'INVALID_ARGUMENT'\n | 'TIMEOUT'\n | 'ABORTED'\n | 'ABORT_ERROR'\n | 'CHALLENGE_MISMATCH'\n | 'UNKNOWN_ERROR';\n\nexport class TryMellonError extends Error {\n readonly code: TryMellonErrorCode;\n readonly details?: unknown;\n readonly isTryMellonError = true;\n\n constructor(code: TryMellonErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'TryMellonError';\n this.code = code;\n this.details = details;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TryMellonError);\n }\n }\n}\n\nconst DEFAULT_MESSAGES: Record<TryMellonErrorCode, string> = {\n NOT_SUPPORTED: 'WebAuthn is not supported in this environment',\n USER_CANCELLED: 'User cancelled the operation',\n PASSKEY_NOT_FOUND: 'Passkey not found',\n SESSION_EXPIRED: 'Session has expired',\n NETWORK_FAILURE: 'Network request failed',\n INVALID_ARGUMENT: 'Invalid argument provided',\n TIMEOUT: 'Operation timed out',\n ABORTED: 'Operation was aborted',\n ABORT_ERROR: 'Operation aborted by user or timeout',\n CHALLENGE_MISMATCH: 'This link was already used or expired. Please try again from your computer.',\n UNKNOWN_ERROR: 'An unknown error occurred',\n};\n\nexport function createError(\n code: TryMellonErrorCode,\n message?: string,\n details?: unknown\n): TryMellonError {\n return new TryMellonError(code, message ?? DEFAULT_MESSAGES[code], details);\n}\n\nexport function isTryMellonError(error: unknown): error is TryMellonError {\n return (\n error instanceof TryMellonError ||\n (typeof error === 'object' &&\n error !== null &&\n 'isTryMellonError' in error &&\n (error as TryMellonError).isTryMellonError === true)\n );\n}\n\nexport function createNotSupportedError(): TryMellonError {\n return createError('NOT_SUPPORTED');\n}\n\nexport function createUserCancelledError(): TryMellonError {\n return createError('USER_CANCELLED');\n}\n\nexport function createNetworkError(cause?: Error): TryMellonError {\n return createError('NETWORK_FAILURE', undefined, {\n cause: cause?.message,\n originalError: cause,\n });\n}\n\nexport function createTimeoutError(): TryMellonError {\n return createError('TIMEOUT');\n}\n\nexport function createInvalidArgumentError(field: string, reason: string): TryMellonError {\n return createError('INVALID_ARGUMENT', `Invalid argument: ${field} - ${reason}`, {\n field,\n reason,\n });\n}\n\nexport function createCredentialError(operation: 'create' | 'get'): TryMellonError {\n return createError('UNKNOWN_ERROR', `Failed to ${operation} credential`, { operation });\n}\n\nexport function createEncodingError(type: 'encode' | 'decode'): TryMellonError {\n return createError(\n 'NOT_SUPPORTED',\n `No base64 ${type === 'encode' ? 'encoding' : 'decoding'} available`,\n { type }\n );\n}\n\nexport function validateNonEmptyString(value: unknown, fieldName: string): asserts value is string {\n if (!value || typeof value !== 'string' || value.trim() === '') {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n}\n\nexport function validateUrl(url: string, fieldName: string): void {\n try {\n const urlObj = new URL(url);\n if (urlObj.protocol !== 'https:' && urlObj.protocol !== 'http:') {\n throw createInvalidArgumentError(fieldName, 'must use http or https protocol');\n }\n } catch (error) {\n if (isTryMellonError(error)) {\n throw error;\n }\n throw createInvalidArgumentError(fieldName, 'must be a valid URL');\n }\n}\n\nexport function validateRange(value: number, fieldName: string, min: number, max: number): void {\n if (!Number.isFinite(value)) {\n throw createInvalidArgumentError(fieldName, 'must be a finite number');\n }\n if (value < min || value > max) {\n throw createInvalidArgumentError(fieldName, `must be between ${min} and ${max}`);\n }\n}\n\nexport function validateBase64Url(s: string, fieldName: string): void {\n if (typeof s !== 'string' || s.length === 0) {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n if (!/^[A-Za-z0-9_-]+$/.test(s)) {\n throw createInvalidArgumentError(fieldName, 'must be a valid base64url string');\n }\n}\n\nconst DOM_EXCEPTION_ERROR_MAP: Record<string, TryMellonErrorCode> = {\n NotAllowedError: 'USER_CANCELLED',\n AbortError: 'ABORTED',\n NotSupportedError: 'NOT_SUPPORTED',\n SecurityError: 'NOT_SUPPORTED',\n InvalidStateError: 'UNKNOWN_ERROR',\n UnknownError: 'UNKNOWN_ERROR',\n};\n\nexport function mapWebAuthnError(error: unknown): TryMellonError {\n if (error instanceof DOMException) {\n const name = error.name;\n const message = error.message || 'WebAuthn operation failed';\n const errorCode = DOM_EXCEPTION_ERROR_MAP[name] ?? 'UNKNOWN_ERROR';\n return createError(errorCode, message, { originalError: error });\n }\n\n if (error instanceof Error) {\n return createError('UNKNOWN_ERROR', error.message, { originalError: error });\n }\n\n return createError('UNKNOWN_ERROR', 'An unknown error occurred', {\n originalError: error,\n });\n}\n","import type { Result } from '../../utils/result';\nimport { err } from '../../utils/result';\nimport { createError, type TryMellonError } from '../../errors';\n\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\nexport function validationError(\n message: string,\n details?: { field?: string; expected?: string; originalData?: unknown }\n): Result<never, TryMellonError> {\n return err(\n createError('UNKNOWN_ERROR', message, {\n ...details,\n originalData: details?.originalData,\n })\n );\n}\n\nexport function required(obj: Record<string, unknown>, key: string): unknown {\n return obj[key];\n}\n\nexport function optionalString(obj: Record<string, unknown>, key: string): string | undefined {\n const v = obj[key];\n return v === undefined ? undefined : typeof v === 'string' ? v : undefined;\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n RegisterStartResponse,\n AuthStartResponse,\n RegisterFinishResponse,\n AuthFinishResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport {\n isObject,\n isString,\n isNumber,\n isBoolean,\n isArray,\n validationError,\n required,\n} from './helpers';\n\nexport function validateRegisterStartResponse(\n data: unknown\n): Result<RegisterStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const rp = required(challenge, 'rp');\n if (\n !isObject(rp) ||\n !isString((rp as Record<string, unknown>).name) ||\n !isString((rp as Record<string, unknown>).id)\n ) {\n return validationError('Invalid API response: challenge.rp must have name and id strings', {\n originalData: data,\n });\n }\n\n const user = required(challenge, 'user');\n if (\n !isObject(user) ||\n !isString((user as Record<string, unknown>).id) ||\n !isString((user as Record<string, unknown>).name) ||\n !isString((user as Record<string, unknown>).displayName)\n ) {\n return validationError(\n 'Invalid API response: challenge.user must have id, name, displayName strings',\n {\n originalData: data,\n }\n );\n }\n\n const challengeStr = required(challenge, 'challenge');\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n\n const pubKeyCredParams = required(challenge, 'pubKeyCredParams');\n if (!isArray(pubKeyCredParams)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of pubKeyCredParams) {\n if (\n !isObject(item) ||\n (item as Record<string, unknown>).type !== 'public-key' ||\n !isNumber((item as Record<string, unknown>).alg)\n ) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n {\n originalData: data,\n }\n );\n }\n }\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const excludeCredentials = challenge.excludeCredentials;\n if (excludeCredentials !== undefined) {\n if (!isArray(excludeCredentials)) {\n return validationError('Invalid API response: excludeCredentials must be array', {\n originalData: data,\n });\n }\n for (const c of excludeCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: excludeCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const authenticatorSelection = challenge.authenticatorSelection;\n if (authenticatorSelection !== undefined && !isObject(authenticatorSelection)) {\n return validationError('Invalid API response: authenticatorSelection must be object', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n challenge: {\n rp: rp as RegisterStartResponse['challenge']['rp'],\n user: user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams: pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n ...(timeout !== undefined && { timeout }),\n ...(excludeCredentials !== undefined && {\n excludeCredentials:\n excludeCredentials as RegisterStartResponse['challenge']['excludeCredentials'],\n }),\n ...(authenticatorSelection !== undefined && {\n authenticatorSelection:\n authenticatorSelection as RegisterStartResponse['challenge']['authenticatorSelection'],\n }),\n },\n });\n}\n\nexport function validateAuthStartResponse(\n data: unknown\n): Result<AuthStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const ch = required(challenge, 'challenge');\n const rpId = required(challenge, 'rpId');\n const allowCredentials = challenge.allowCredentials;\n if (!isString(ch)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isString(rpId)) {\n return validationError('Invalid API response: challenge.rpId must be string', {\n originalData: data,\n });\n }\n if (allowCredentials !== undefined && !isArray(allowCredentials)) {\n return validationError('Invalid API response: allowCredentials must be array', {\n originalData: data,\n });\n }\n if (allowCredentials) {\n for (const c of allowCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: allowCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const userVerification = challenge.userVerification;\n if (\n userVerification !== undefined &&\n !['required', 'preferred', 'discouraged'].includes(String(userVerification))\n ) {\n return validationError(\n 'Invalid API response: userVerification must be required|preferred|discouraged',\n {\n originalData: data,\n }\n );\n }\n\n return ok({\n session_id,\n challenge: {\n challenge: ch,\n rpId,\n allowCredentials:\n (allowCredentials as AuthStartResponse['challenge']['allowCredentials']) ?? [],\n ...(timeout !== undefined && { timeout }),\n ...(userVerification !== undefined && {\n userVerification: userVerification as AuthStartResponse['challenge']['userVerification'],\n }),\n },\n });\n}\n\nexport function validateRegisterFinishResponse(\n data: unknown\n): Result<RegisterFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const credential_id = required(data, 'credential_id');\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const userId = required(user, 'user_id');\n const externalUserId = required(user, 'external_user_id');\n if (!isString(userId) || !isString(externalUserId)) {\n return validationError(\n 'Invalid API response: user must have user_id and external_user_id strings',\n {\n originalData: data,\n }\n );\n }\n\n const email = user.email;\n const metadata = user.metadata;\n if (email !== undefined && !isString(email)) {\n return validationError('Invalid API response: user.email must be string', {\n originalData: data,\n });\n }\n if (metadata !== undefined && (typeof metadata !== 'object' || metadata === null)) {\n return validationError('Invalid API response: user.metadata must be object', {\n originalData: data,\n });\n }\n\n return ok({\n credential_id,\n status,\n session_token,\n user: {\n user_id: userId,\n external_user_id: externalUserId,\n ...(email !== undefined && { email }),\n ...(metadata !== undefined && { metadata: metadata as Record<string, unknown> }),\n },\n });\n}\n\nexport function validateAuthFinishResponse(\n data: unknown\n): Result<AuthFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const authenticated = required(data, 'authenticated');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const signals = required(data, 'signals');\n\n if (!isBoolean(authenticated)) {\n return validationError('Invalid API response: authenticated must be boolean', {\n field: 'authenticated',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const userId = required(user, 'user_id');\n const externalUserId = required(user, 'external_user_id');\n if (!isString(userId) || !isString(externalUserId)) {\n return validationError(\n 'Invalid API response: user must have user_id and external_user_id strings',\n {\n originalData: data,\n }\n );\n }\n\n if (signals !== undefined && !isObject(signals)) {\n return validationError('Invalid API response: signals must be object', {\n originalData: data,\n });\n }\n\n return ok({\n authenticated,\n session_token,\n user: {\n user_id: userId,\n external_user_id: externalUserId,\n ...(user.email !== undefined && { email: user.email as string }),\n ...(user.metadata !== undefined && { metadata: user.metadata as Record<string, unknown> }),\n },\n signals: signals as AuthFinishResponse['signals'],\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { SessionValidateResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isBoolean, required, validationError } from './helpers';\n\nexport function validateSessionValidateResponse(\n data: unknown\n): Result<SessionValidateResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const valid = required(data, 'valid');\n const user_id = required(data, 'user_id');\n const external_user_id = required(data, 'external_user_id');\n const tenant_id = required(data, 'tenant_id');\n const app_id = required(data, 'app_id');\n\n if (!isBoolean(valid)) {\n return validationError('Invalid API response: valid must be boolean', {\n field: 'valid',\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n field: 'user_id',\n originalData: data,\n });\n }\n if (!isString(external_user_id)) {\n return validationError('Invalid API response: external_user_id must be string', {\n field: 'external_user_id',\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n field: 'tenant_id',\n originalData: data,\n });\n }\n if (!isString(app_id)) {\n return validationError('Invalid API response: app_id must be string', {\n field: 'app_id',\n originalData: data,\n });\n }\n\n return ok({\n valid,\n user_id,\n external_user_id,\n tenant_id,\n app_id,\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, required, validationError } from './helpers';\n\nexport function validateEmailVerifyResponse(\n data: unknown\n): Result<{ sessionToken: string }, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const sessionToken = required(data, 'sessionToken');\n if (!isString(sessionToken)) {\n return validationError('Invalid API response: sessionToken must be string', {\n field: 'sessionToken',\n originalData: data,\n });\n }\n\n return ok({ sessionToken });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterResponse,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteResponse,\n RegisterStartResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isNumber, isArray, required, validationError } from './helpers';\n\nconst ONBOARDING_STATUSES = ['pending_passkey', 'pending_data', 'completed'] as const;\nconst REGISTER_PASSKEY_STATUSES = ['pending_data', 'completed'] as const;\n\nexport function validateOnboardingStartResponse(\n data: unknown\n): Result<OnboardingStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n field: 'onboarding_url',\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n field: 'expires_in',\n originalData: data,\n });\n }\n\n return ok({ session_id, onboarding_url, expires_in });\n}\n\nexport function validateOnboardingStatusResponse(\n data: unknown\n): Result<OnboardingStatusResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (\n !isString(status) ||\n !ONBOARDING_STATUSES.includes(status as (typeof ONBOARDING_STATUSES)[number])\n ) {\n return validationError(\n 'Invalid API response: status must be pending_passkey|pending_data|completed',\n {\n field: 'status',\n originalData: data,\n }\n );\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n originalData: data,\n });\n }\n\n return ok({\n status: status as OnboardingStatusResponse['status'],\n onboarding_url,\n expires_in,\n });\n}\n\n/** Response may include optional challenge for same-device passkey registration */\nexport type OnboardingRegisterResponseWithChallenge = OnboardingRegisterResponse & {\n challenge?: RegisterStartResponse['challenge'];\n};\n\nexport function validateOnboardingRegisterResponse(\n data: unknown\n): Result<OnboardingRegisterResponseWithChallenge, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (status !== 'pending_passkey') {\n return validationError('Invalid API response: status must be pending_passkey', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n\n const challenge = data.challenge;\n let parsedChallenge: RegisterStartResponse['challenge'] | undefined;\n if (challenge !== undefined) {\n const chResult = validateOnboardingChallenge(challenge);\n if (!chResult.ok) return chResult;\n parsedChallenge = chResult.value;\n }\n\n return ok({\n session_id,\n status: 'pending_passkey',\n onboarding_url,\n ...(parsedChallenge !== undefined && { challenge: parsedChallenge }),\n });\n}\n\nfunction validateOnboardingChallenge(\n data: unknown\n): Result<RegisterStartResponse['challenge'], TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: challenge must be object', {\n originalData: data,\n });\n }\n\n const rp = required(data, 'rp');\n const user = required(data, 'user');\n const challengeStr = required(data, 'challenge');\n const pubKeyCredParams = required(data, 'pubKeyCredParams');\n\n if (\n !isObject(rp) ||\n !isString((rp as Record<string, unknown>).name) ||\n !isString((rp as Record<string, unknown>).id)\n ) {\n return validationError('Invalid API response: challenge.rp must have name and id', {\n originalData: data,\n });\n }\n if (\n !isObject(user) ||\n !isString((user as Record<string, unknown>).id) ||\n !isString((user as Record<string, unknown>).name) ||\n !isString((user as Record<string, unknown>).displayName)\n ) {\n return validationError('Invalid API response: challenge.user must have id, name, displayName', {\n originalData: data,\n });\n }\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isArray(pubKeyCredParams)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of pubKeyCredParams) {\n if (\n !isObject(item) ||\n (item as Record<string, unknown>).type !== 'public-key' ||\n !isNumber((item as Record<string, unknown>).alg)\n ) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n {\n originalData: data,\n }\n );\n }\n }\n\n return ok({\n rp: rp as RegisterStartResponse['challenge']['rp'],\n user: user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams: pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n });\n}\n\nexport function validateOnboardingRegisterPasskeyResponse(\n data: unknown\n): Result<OnboardingRegisterPasskeyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (\n !isString(status) ||\n !REGISTER_PASSKEY_STATUSES.includes(status as (typeof REGISTER_PASSKEY_STATUSES)[number])\n ) {\n return validationError('Invalid API response: status must be pending_data|completed', {\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n status: status as OnboardingRegisterPasskeyResponse['status'],\n user_id,\n tenant_id,\n });\n}\n\nexport function validateOnboardingCompleteResponse(\n data: unknown\n): Result<OnboardingCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n const session_token = required(data, 'session_token');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (status !== 'completed') {\n return validationError('Invalid API response: status must be completed', {\n originalData: data,\n });\n }\n if (!isString(user_id) || !isString(tenant_id) || !isString(session_token)) {\n return validationError(\n 'Invalid API response: user_id, tenant_id, session_token must be strings',\n { originalData: data }\n );\n }\n\n return ok({\n session_id,\n status: 'completed',\n user_id,\n tenant_id,\n session_token,\n });\n}\n","import { ok } from '../../utils/result';\nimport type { Result } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, validationError } from './helpers';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n} from '../../types';\n\nfunction isCreationOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return (\n typeof o.challenge === 'string' &&\n o.rp != null &&\n typeof o.rp === 'object' &&\n o.user != null &&\n typeof o.user === 'object' &&\n Array.isArray((o as { pubKeyCredParams?: unknown }).pubKeyCredParams)\n );\n}\n\nfunction isRequestOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return typeof o.challenge === 'string' && typeof o.rpId === 'string';\n}\n\nexport function validateCrossDeviceInitResponse(\n data: unknown\n): Result<CrossDeviceInitResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = data.session_id;\n const qr_url = data.qr_url;\n const expires_at = data.expires_at;\n\n if (!isString(session_id) || !isString(qr_url) || !isString(expires_at)) {\n return validationError('Invalid API response: missing required fields', { originalData: data });\n }\n\n return ok({\n session_id,\n qr_url,\n expires_at,\n });\n}\n\nexport function validateCrossDeviceStatusResponse(\n data: unknown\n): Result<CrossDeviceStatusResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = data.status;\n if (!isString(status) || !['pending', 'authenticated', 'completed'].includes(status)) {\n return validationError('Invalid API response: invalid status', { originalData: data });\n }\n\n return ok({\n status: status as CrossDeviceStatusResult['status'],\n user_id: data.user_id as string | undefined,\n session_token: data.session_token as string | undefined,\n });\n}\n\nexport function validateCrossDeviceContextResponse(\n data: unknown\n): Result<CrossDeviceContextResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const rawType = data.type;\n const type =\n rawType === 'registration' ? 'registration' : rawType === 'auth' ? 'auth' : ('auth' as const);\n\n const options = data.options;\n if (!isObject(options)) {\n return validationError('Invalid API response: options are required', { originalData: data });\n }\n\n if (type === 'registration') {\n if (!isCreationOptionsShape(options)) {\n return validationError(\n 'Invalid API response: registration options must have challenge, rp, user, pubKeyCredParams',\n { originalData: data }\n );\n }\n return ok({\n type: 'registration',\n options,\n } as CrossDeviceContextResult);\n }\n\n if (!isRequestOptionsShape(options)) {\n return validationError('Invalid API response: auth options must have challenge and rpId', {\n originalData: data,\n });\n }\n return ok({ type: 'auth', options } as CrossDeviceContextResult);\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { RecoveryVerifyResponse, RecoveryCompleteResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, required, validationError } from './helpers';\n\nexport function validateRecoveryVerifyResponse(\n data: unknown\n): Result<RecoveryVerifyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const challenge = required(data, 'challenge');\n const recovery_session_id = required(data, 'recovery_session_id');\n\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n if (!isString(recovery_session_id)) {\n return validationError('Invalid API response: recovery_session_id must be string', {\n field: 'recovery_session_id',\n originalData: data,\n });\n }\n\n return ok({\n challenge: challenge as Record<string, unknown>,\n recovery_session_id,\n });\n}\n\nexport function validateRecoveryCompleteResponse(\n data: unknown\n): Result<RecoveryCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const credential_id = required(data, 'credential_id');\n\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const user_id = required(user, 'user_id');\n if (!isString(user_id)) {\n return validationError('Invalid API response: user.user_id must be string', {\n field: 'user.user_id',\n originalData: data,\n });\n }\n\n const userObj = user as Record<string, unknown>;\n return ok({\n status,\n session_token,\n credential_id,\n user: {\n user_id,\n external_user_id: isString(userObj.external_user_id) ? userObj.external_user_id : undefined,\n email: isString(userObj.email) ? userObj.email : undefined,\n metadata: isObject(userObj.metadata)\n ? (userObj.metadata as Record<string, unknown>)\n : undefined,\n },\n });\n}\n","import type { HttpClient } from './http-client';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport {\n validateRegisterStartResponse,\n validateAuthStartResponse,\n validateRegisterFinishResponse,\n validateAuthFinishResponse,\n validateSessionValidateResponse,\n validateEmailVerifyResponse,\n validateOnboardingStartResponse,\n validateOnboardingStatusResponse,\n validateOnboardingRegisterResponse,\n validateOnboardingRegisterPasskeyResponse,\n validateOnboardingCompleteResponse,\n validateCrossDeviceInitResponse,\n validateCrossDeviceStatusResponse,\n validateCrossDeviceContextResponse,\n validateRecoveryVerifyResponse,\n validateRecoveryCompleteResponse,\n} from './validators';\nimport type {\n RegisterStartRequest,\n RegisterStartResponse,\n AuthStartRequest,\n AuthStartResponse,\n RegisterFinishRequest,\n RegisterFinishResponse,\n AuthFinishRequest,\n AuthFinishResponse,\n SessionValidateResponse,\n OnboardingStartRequest,\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterPasskeyRequest,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteRequest,\n OnboardingCompleteResponse,\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n CrossDeviceVerifyRequest,\n CrossDeviceVerifyRegistrationRequest,\n RecoveryVerifyResponse,\n RecoveryCompleteResponse,\n} from '../types';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\n\nexport class ApiClient {\n constructor(\n private readonly httpClient: HttpClient,\n private readonly baseUrl: string,\n private readonly defaultHeaders: Record<string, string> = {}\n ) {}\n\n private mergeHeaders(extra?: Record<string, string>): Record<string, string> {\n return { ...this.defaultHeaders, ...extra };\n }\n\n private async post<Req, Res>(\n path: string,\n body: Req,\n validate: (data: unknown) => Result<Res, TryMellonError>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.post<unknown>(url, body, this.mergeHeaders());\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n private async get<Res>(\n path: string,\n validate: (data: unknown) => Result<Res, TryMellonError>,\n headers?: Record<string, string>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.get<unknown>(url, this.mergeHeaders(headers));\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n async startRegister(\n request: RegisterStartRequest\n ): Promise<Result<RegisterStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/start', request, validateRegisterStartResponse);\n }\n\n async startAuth(request: AuthStartRequest): Promise<Result<AuthStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/start', request, validateAuthStartResponse);\n }\n\n async finishRegister(\n request: RegisterFinishRequest\n ): Promise<Result<RegisterFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/finish', request, validateRegisterFinishResponse);\n }\n\n async finishAuthentication(\n request: AuthFinishRequest\n ): Promise<Result<AuthFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/finish', request, validateAuthFinishResponse);\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n return this.get('/v1/sessions/validate', validateSessionValidateResponse, {\n Authorization: `Bearer ${sessionToken}`,\n });\n }\n\n async startEmailFallback(options: {\n userId: string;\n email: string;\n }): Promise<Result<void, TryMellonError>> {\n const url = `${this.baseUrl}/v1/fallback/email/start`;\n const result = await this.httpClient.post<unknown>(\n url,\n { userId: options.userId, email: options.email },\n this.mergeHeaders()\n );\n if (!result.ok) return err(result.error);\n return ok(undefined);\n }\n\n async verifyEmailCode(\n userId: string,\n code: string\n ): Promise<Result<{ sessionToken: string }, TryMellonError>> {\n return this.post('/v1/fallback/email/verify', { userId, code }, validateEmailVerifyResponse);\n }\n\n async startOnboarding(\n request: OnboardingStartRequest\n ): Promise<Result<OnboardingStartResponse, TryMellonError>> {\n return this.post('/onboarding/start', request, validateOnboardingStartResponse);\n }\n\n async getOnboardingStatus(\n sessionId: string\n ): Promise<Result<OnboardingStatusResponse, TryMellonError>> {\n return this.get(`/onboarding/${sessionId}/status`, validateOnboardingStatusResponse);\n }\n\n async getOnboardingRegister(\n sessionId: string\n ): Promise<Result<OnboardingRegisterResponseWithChallenge, TryMellonError>> {\n return this.get(`/onboarding/${sessionId}/register`, validateOnboardingRegisterResponse);\n }\n\n async registerOnboardingPasskey(\n sessionId: string,\n request: OnboardingRegisterPasskeyRequest\n ): Promise<Result<OnboardingRegisterPasskeyResponse, TryMellonError>> {\n return this.post(\n `/onboarding/${sessionId}/register-passkey`,\n request,\n validateOnboardingRegisterPasskeyResponse\n );\n }\n\n async completeOnboarding(\n sessionId: string,\n request: OnboardingCompleteRequest\n ): Promise<Result<OnboardingCompleteResponse, TryMellonError>> {\n return this.post(\n `/onboarding/${sessionId}/complete`,\n request,\n validateOnboardingCompleteResponse\n );\n }\n\n async initCrossDeviceAuth(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.post('/v1/auth/cross-device/init', {}, validateCrossDeviceInitResponse);\n }\n\n async initCrossDeviceRegistration(options: {\n externalUserId: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.post(\n '/v1/auth/cross-device/init-registration',\n { external_user_id: options.externalUserId },\n validateCrossDeviceInitResponse\n );\n }\n\n async getCrossDeviceStatus(\n sessionId: string\n ): Promise<Result<CrossDeviceStatusResult, TryMellonError>> {\n return this.get(`/v1/auth/cross-device/status/${sessionId}`, validateCrossDeviceStatusResponse);\n }\n\n /**\n * Fetches WebAuthn options for the cross-device session.\n * Contract: response is CrossDeviceContextResult (auth | registration).\n * Use result.value.type to branch: 'auth' → credentials.get + verify;\n * 'registration' → credentials.create + verify-registration.\n */\n async getCrossDeviceContext(\n sessionId: string\n ): Promise<Result<CrossDeviceContextResult, TryMellonError>> {\n return this.get(\n `/v1/auth/cross-device/context/${sessionId}`,\n validateCrossDeviceContextResponse\n );\n }\n\n async verifyCrossDeviceAuth(\n request: CrossDeviceVerifyRequest\n ): Promise<Result<void, TryMellonError>> {\n const url = `${this.baseUrl}/v1/auth/cross-device/verify`;\n const result = await this.httpClient.post<unknown>(url, request, this.mergeHeaders());\n if (!result.ok) return err(result.error);\n return ok(undefined);\n }\n\n async verifyCrossDeviceRegistration(\n request: CrossDeviceVerifyRegistrationRequest\n ): Promise<Result<void, TryMellonError>> {\n const url = `${this.baseUrl}/v1/auth/cross-device/verify-registration`;\n const result = await this.httpClient.post<unknown>(url, request, this.mergeHeaders());\n if (!result.ok) return err(result.error);\n return ok(undefined);\n }\n\n async verifyAccountRecoveryOtp(\n externalUserId: string,\n otp: string\n ): Promise<Result<RecoveryVerifyResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/verify',\n { external_id: externalUserId, otp },\n validateRecoveryVerifyResponse\n );\n }\n\n async completeAccountRecovery(\n recoverySessionId: string,\n credential: Record<string, unknown>\n ): Promise<Result<RecoveryCompleteResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/complete',\n { recovery_session_id: recoverySessionId, credential },\n validateRecoveryCompleteResponse\n );\n }\n}\n","import type { HttpClient } from './http-client';\nimport type { Logger } from './ports/logger';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { createError, type TryMellonError, type TryMellonErrorCode } from '../errors';\n\nconst RETRY_DELAY_CAP_MS = 30_000;\n\n/**\n * Generates a unique request ID. Uses globalThis.crypto.randomUUID only (Elite: no Node crypto).\n * @throws Error when Web Crypto API is not available (Edge/browser must provide it).\n */\nfunction generateRequestId(): string {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n return globalThis.crypto.randomUUID();\n }\n throw new Error('Web Crypto API is required but not available.');\n}\n\n/**\n * Exponential backoff delay for a given attempt (0-based).\n * Cap at RETRY_DELAY_CAP_MS.\n */\nexport function getRetryDelayMs(attempt: number, baseMs: number): number {\n const delay = baseMs * Math.pow(2, attempt);\n return Math.min(delay, RETRY_DELAY_CAP_MS);\n}\n\nfunction shouldRetryOnStatus(method: string, status: number): boolean {\n if (method !== 'GET') return false;\n return status >= 500 || status === 429;\n}\n\nexport class FetchHttpClient implements HttpClient {\n constructor(\n private readonly timeoutMs: number,\n private readonly maxRetries: number = 0,\n private readonly retryDelayMs: number = 1000,\n private readonly logger?: Logger\n ) {}\n\n async get<T>(url: string, headers?: Record<string, string>): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, { method: 'GET', headers });\n }\n\n async post<T>(\n url: string,\n body: unknown,\n headers?: Record<string, string>\n ): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: { 'Content-Type': 'application/json', ...headers },\n });\n }\n\n private async request<T>(url: string, config: RequestInit): Promise<Result<T, TryMellonError>> {\n const method = (config.method ?? 'GET').toUpperCase();\n const requestId = generateRequestId();\n const headers = new Headers(config.headers as HeadersInit);\n headers.set('X-Request-Id', requestId);\n\n if (this.logger) {\n this.logger.debug('request', { requestId, url, method });\n }\n\n let lastError: TryMellonError | Error | unknown;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(url, {\n ...config,\n headers,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n let errorData: unknown;\n try {\n errorData = await response.json();\n } catch {\n // Ignore JSON parse error\n }\n\n const body = errorData as { message?: string; error?: string } | undefined;\n const message = body?.message ?? response.statusText;\n const rawCode = body?.error;\n const code: TryMellonErrorCode =\n rawCode === 'challenge_mismatch'\n ? 'CHALLENGE_MISMATCH'\n : ((rawCode as TryMellonErrorCode | undefined) ?? 'NETWORK_FAILURE');\n const errResult = createError(code, message, {\n requestId,\n status: response.status,\n statusText: response.statusText,\n data: errorData,\n });\n\n if (shouldRetryOnStatus(method, response.status) && attempt < this.maxRetries) {\n lastError = errResult;\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n continue;\n }\n\n return err(errResult);\n }\n\n if (response.status === 204) {\n return ok(undefined as T);\n }\n const contentLength = response.headers.get('content-length');\n if (contentLength === '0') {\n return ok(undefined as T);\n }\n const data = (await response.json()) as T;\n return ok(data);\n } finally {\n clearTimeout(timeoutId);\n }\n } catch (error) {\n lastError = error;\n const isGet = method === 'GET';\n if (isGet && attempt < this.maxRetries) {\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n } else {\n break;\n }\n }\n }\n\n if (lastError instanceof Error && lastError.name === 'AbortError') {\n return err(createError('TIMEOUT', 'Request timed out', { requestId }));\n }\n\n return err(\n createError(\n 'NETWORK_FAILURE',\n lastError instanceof Error ? lastError.message : 'Request failed',\n { requestId, cause: lastError }\n )\n );\n }\n}\n","import type { ClientStatus } from '../types';\n\nexport function isWebAuthnSupported(): boolean {\n try {\n if (typeof navigator === 'undefined' || !navigator.credentials) {\n return false;\n }\n\n if (typeof PublicKeyCredential === 'undefined') {\n return false;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function isPlatformAuthenticatorAvailable(): Promise<boolean> {\n try {\n if (!isWebAuthnSupported()) {\n return false;\n }\n\n if (typeof PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable !== 'function') {\n return false;\n }\n\n return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n } catch {\n return false;\n }\n}\n\nexport async function getClientStatus(): Promise<ClientStatus> {\n const isPasskeySupported = isWebAuthnSupported();\n const platformAuthenticatorAvailable = await isPlatformAuthenticatorAvailable();\n\n return {\n isPasskeySupported,\n platformAuthenticatorAvailable,\n recommendedFlow: isPasskeySupported ? 'passkey' : 'fallback',\n };\n}\n","import { createEncodingError } from '../errors';\n\n/**\n * Encodes an ArrayBuffer to base64url using globalThis.btoa (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when btoa is unavailable\n */\nexport function base64UrlEncode(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n const binary = Array.from(bytes, (b) => String.fromCharCode(b)).join('');\n\n if (typeof globalThis.btoa === 'undefined') {\n throw createEncodingError('encode');\n }\n const base64 = globalThis.btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Decodes a base64url string to Uint8Array using globalThis.atob (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when atob is unavailable\n */\nexport function base64UrlDecode(s: string): Uint8Array {\n if (typeof globalThis.atob === 'undefined') {\n throw createEncodingError('decode');\n }\n\n const base64 = s.replace(/-/g, '+').replace(/_/g, '/');\n const padding = base64.length % 4;\n const padded = padding === 0 ? base64 : base64 + '='.repeat(4 - padding);\n const binary = globalThis.atob(padded);\n\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n\n/** Decodes base64url to ArrayBuffer (delegates to base64UrlDecode). */\nexport function base64UrlDecodeToArrayBuffer(s: string): ArrayBuffer {\n const bytes = base64UrlDecode(s);\n const buffer = new ArrayBuffer(bytes.length);\n new Uint8Array(buffer).set(bytes);\n return buffer;\n}\n","import { createCredentialError } from '../errors';\n\nexport function validateCredentialStructure(\n credential: unknown,\n operation: 'create' | 'get' = 'create'\n): asserts credential is PublicKeyCredential {\n if (\n !credential ||\n typeof credential !== 'object' ||\n !('id' in credential) ||\n !('rawId' in credential) ||\n !('response' in credential)\n ) {\n throw createCredentialError(operation);\n }\n}\n","import { createError } from '../errors';\nimport { base64UrlEncode } from '../utils/base64url';\nimport type { RegisterFinishRequest, AuthFinishRequest } from '../types';\n\ntype SerializedCredentialForRegister = RegisterFinishRequest['credential'];\ntype SerializedCredentialForAuth = AuthFinishRequest['credential'];\n\n/**\n * Type guard para verificar si una respuesta de credencial es válida.\n */\nfunction isValidCredentialResponse(\n response: unknown\n): response is AuthenticatorAssertionResponse | AuthenticatorAttestationResponse {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'clientDataJSON' in response &&\n response.clientDataJSON instanceof ArrayBuffer\n );\n}\n\n/**\n * Serializa una credencial para registro (finish).\n * Incluye attestationObject requerido para la verificación de registro.\n *\n * @param credential - Credencial WebAuthn obtenida de navigator.credentials.create()\n * @returns Credencial serializada con formato Base64URL\n * @throws {TryMellonError} Si la credencial no tiene la estructura esperada para registro\n */\nexport function serializeCredentialForRegister(\n credential: PublicKeyCredential\n): SerializedCredentialForRegister {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('attestationObject' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for register: attestationObject is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const attestationObject = (response as AuthenticatorAttestationResponse).attestationObject;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n clientDataJSON: base64UrlEncode(clientDataJSON),\n attestationObject: base64UrlEncode(attestationObject),\n },\n type: 'public-key',\n };\n}\n\n/**\n * Serializa una credencial para autenticación (finish).\n * Incluye authenticatorData, signature, y opcionalmente userHandle.\n *\n * @param credential - Credencial WebAuthn obtenida de navigator.credentials.get()\n * @returns Credencial serializada con formato Base64URL\n * @throws {TryMellonError} Si la credencial no tiene la estructura esperada para autenticación\n */\nexport function serializeCredentialForAuth(\n credential: PublicKeyCredential\n): SerializedCredentialForAuth {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('authenticatorData' in response) || !('signature' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for auth: authenticatorData or signature is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const authenticatorData = (response as AuthenticatorAssertionResponse).authenticatorData;\n const signature = (response as AuthenticatorAssertionResponse).signature;\n const userHandle = (response as AuthenticatorAssertionResponse).userHandle;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n authenticatorData: base64UrlEncode(authenticatorData),\n clientDataJSON: base64UrlEncode(clientDataJSON),\n signature: base64UrlEncode(signature),\n ...(userHandle && { userHandle: base64UrlEncode(userHandle) }),\n },\n type: 'public-key',\n };\n}\n","import { isWebAuthnSupported } from '../utils/support';\nimport {\n mapWebAuthnError,\n createNotSupportedError,\n createInvalidArgumentError,\n validateBase64Url,\n} from '../errors';\nimport { base64UrlDecodeToArrayBuffer } from '../utils/base64url';\nimport { validateCredentialStructure } from '../utils/validation';\nimport type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type {\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n RegisterStartResponse,\n AuthStartResponse,\n} from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\n\n/**\n * Crea las opciones de creación de credencial para WebAuthn.\n * Convierte la respuesta del servidor en formato WebAuthn API.\n * WebAuthn protocol: challenge and rp.id are taken from the server only; do not override.\n * Exported for use by OnboardingManager (same-device passkey registration).\n */\nexport function createRegistrationOptions(\n challenge: RegisterStartResponse['challenge'],\n authenticatorType?: 'platform' | 'cross-platform'\n): Result<CredentialCreationOptions, TryMellonError> {\n try {\n validateBase64Url(challenge.challenge, 'challenge');\n validateBase64Url(challenge.user.id, 'user.id');\n\n const challengeBuffer = base64UrlDecodeToArrayBuffer(challenge.challenge);\n const userIdBuffer = base64UrlDecodeToArrayBuffer(challenge.user.id);\n\n // Construir authenticatorSelection: priorizar servidor, permitir override de authenticatorType\n let authenticatorSelection: AuthenticatorSelectionCriteria = {\n userVerification: 'preferred',\n };\n\n if (challenge.authenticatorSelection) {\n // Usar valores del servidor como base\n authenticatorSelection = {\n ...challenge.authenticatorSelection,\n };\n }\n\n // Si el usuario especifica authenticatorType, sobrescribir authenticatorAttachment\n if (authenticatorType) {\n authenticatorSelection = {\n ...authenticatorSelection,\n authenticatorAttachment: authenticatorType,\n };\n }\n\n const publicKey: PublicKeyCredentialCreationOptions = {\n rp: {\n id: challenge.rp.id,\n name: challenge.rp.name,\n },\n user: {\n id: userIdBuffer,\n name: challenge.user.name,\n displayName: challenge.user.displayName,\n },\n challenge: challengeBuffer,\n pubKeyCredParams: challenge.pubKeyCredParams,\n ...(challenge.timeout !== undefined && { timeout: challenge.timeout }),\n attestation: 'none',\n authenticatorSelection,\n ...(challenge.excludeCredentials && {\n excludeCredentials: challenge.excludeCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n };\n\n return ok({ publicKey });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Crea las opciones de autenticación para WebAuthn.\n * Convierte la respuesta del servidor en formato WebAuthn API.\n * WebAuthn protocol: challenge and rpId are taken from the server only; do not override.\n */\nexport function createAuthenticationOptions(\n challenge: AuthStartResponse['challenge'],\n mediation?: AuthenticateOptions['mediation']\n): Result<CredentialRequestOptions, TryMellonError> {\n try {\n validateBase64Url(challenge.challenge, 'challenge');\n const challengeBuffer = base64UrlDecodeToArrayBuffer(challenge.challenge);\n\n return ok({\n publicKey: {\n challenge: challengeBuffer,\n rpId: challenge.rpId,\n ...(challenge.timeout !== undefined && { timeout: challenge.timeout }),\n userVerification: challenge.userVerification ?? 'preferred',\n ...(challenge.allowCredentials && {\n allowCredentials: challenge.allowCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n },\n ...(mediation !== undefined && { mediation }),\n });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Registra una nueva passkey para un usuario.\n * Maneja el flujo completo de registro WebAuthn.\n */\nexport async function registerPasskey(\n options: RegisterOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RegisterResult, TryMellonError>> {\n try {\n eventEmitter.emit('start', { type: 'start', operation: 'register' });\n\n if (!isWebAuthnSupported()) {\n const error = createNotSupportedError();\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n const extId = options.externalUserId ?? options.external_user_id;\n\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 1. Obtener challenge del servidor\n const startResult = await apiClient.startRegister({\n external_user_id: extId,\n });\n\n if (!startResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: startResult.error });\n return err(startResult.error);\n }\n\n // 2. Crear opciones de creación de credencial\n const creationOptionsResult = createRegistrationOptions(\n startResult.value.challenge,\n options.authenticatorType\n );\n\n if (!creationOptionsResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: creationOptionsResult.error });\n return err(creationOptionsResult.error);\n }\n\n const creationOptions = {\n ...creationOptionsResult.value,\n ...(options.signal && { signal: options.signal }),\n };\n\n // 3. Solicitar al navegador la creación de la credencial\n const credential = (await navigator.credentials.create(creationOptions)) as PublicKeyCredential;\n\n if (!credential) {\n const error = createInvalidArgumentError('credential', 'creation failed');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n try {\n validateCredentialStructure(credential);\n } catch (e) {\n const error = mapWebAuthnError(e);\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 4. Completar registro en el servidor\n const finishResult = await apiClient.finishRegister({\n session_id: startResult.value.session_id,\n credential: serializeCredentialForRegister(credential),\n });\n\n if (!finishResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: finishResult.error });\n return err(finishResult.error);\n }\n\n const result: RegisterResult = {\n success: true,\n credentialId: finishResult.value.credential_id,\n credential_id: finishResult.value.credential_id,\n status: finishResult.value.status,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n };\n\n eventEmitter.emit('success', { type: 'success', operation: 'register' });\n return ok(result);\n } catch (error) {\n const tryMellonError = mapWebAuthnError(error);\n eventEmitter.emit('error', { type: 'error', error: tryMellonError });\n return err(tryMellonError);\n }\n}\n\n/**\n * Autentica un usuario usando su passkey.\n * Maneja el flujo completo de autenticación WebAuthn.\n */\nexport async function authenticatePasskey(\n options: AuthenticateOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<AuthenticateResult, TryMellonError>> {\n try {\n eventEmitter.emit('start', { type: 'start', operation: 'authenticate' });\n\n if (!isWebAuthnSupported()) {\n const error = createNotSupportedError();\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n const extId = options.externalUserId ?? options.external_user_id;\n const hasUserId = extId !== undefined && typeof extId === 'string' && extId.trim() !== '';\n\n // 1. Obtener challenge del servidor (sin external_user_id = discoverable passkeys)\n const startResult = await apiClient.startAuth(\n hasUserId ? { external_user_id: (extId as string).trim() } : {}\n );\n\n if (!startResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: startResult.error });\n return err(startResult.error);\n }\n\n // 2. Crear opciones de autenticación\n const requestOptionsResult = createAuthenticationOptions(\n startResult.value.challenge,\n options.mediation\n );\n\n if (!requestOptionsResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: requestOptionsResult.error });\n return err(requestOptionsResult.error);\n }\n\n const requestOptions = {\n ...requestOptionsResult.value,\n ...(options.signal && { signal: options.signal }),\n };\n\n // 3. Solicitar al navegador la autenticación\n const credential = (await navigator.credentials.get(requestOptions)) as PublicKeyCredential;\n\n if (!credential) {\n const error = createInvalidArgumentError('credential', 'retrieval failed');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n try {\n validateCredentialStructure(credential);\n } catch (e) {\n const error = mapWebAuthnError(e);\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 4. Completar autenticación en el servidor\n const finishResult = await apiClient.finishAuthentication({\n session_id: startResult.value.session_id,\n credential: serializeCredentialForAuth(credential),\n });\n\n if (!finishResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: finishResult.error });\n return err(finishResult.error);\n }\n\n const result: AuthenticateResult = {\n authenticated: finishResult.value.authenticated,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n signals: finishResult.value.signals,\n };\n\n eventEmitter.emit('success', { type: 'success', operation: 'authenticate' });\n return ok(result);\n } catch (error) {\n const tryMellonError = mapWebAuthnError(error);\n eventEmitter.emit('error', { type: 'error', error: tryMellonError });\n return err(tryMellonError);\n }\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type { OnboardingStartOptions, OnboardingCompleteResult } from '../types';\nimport { createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class OnboardingManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Executes the full onboarding flow in a single call.\n * 1. Starts onboarding\n * 2. Polls for 'pending_passkey' or 'completed' status\n * 3. If pending_passkey: when API returns challenge, registers passkey (WebAuthn) then completes onboarding\n * 4. If pending_passkey but API does not return challenge: returns NOT_SUPPORTED with onboarding_url for user to complete elsewhere\n */\n async startFlow(\n options: OnboardingStartOptions & { company_name?: string }\n ): Promise<Result<OnboardingCompleteResult, TryMellonError>> {\n const startResult = await this.apiClient.startOnboarding({ user_role: options.user_role });\n if (!startResult.ok) return err(startResult.error);\n\n const { session_id } = startResult.value;\n\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n\n const statusResult = await this.apiClient.getOnboardingStatus(session_id);\n if (!statusResult.ok) return err(statusResult.error);\n\n const status = statusResult.value.status;\n const onboarding_url = statusResult.value.onboarding_url;\n\n if (status === 'pending_passkey') {\n const registerInfoResult = await this.apiClient.getOnboardingRegister(session_id);\n if (!registerInfoResult.ok) return err(registerInfoResult.error);\n\n const registerInfo = registerInfoResult.value as OnboardingRegisterResponseWithChallenge;\n\n if (!registerInfo.challenge) {\n return err(\n createError(\n 'NOT_SUPPORTED',\n 'Onboarding requires user action - complete passkey registration at the provided onboarding_url',\n { onboarding_url }\n )\n );\n }\n\n const creationOptionsResult = createRegistrationOptions(registerInfo.challenge);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n const registerPasskeyResult = await this.apiClient.registerOnboardingPasskey(session_id, {\n credential: serializedCredential,\n challenge: registerInfo.challenge.challenge,\n });\n if (!registerPasskeyResult.ok) return err(registerPasskeyResult.error);\n\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n\n if (status === 'completed') {\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n }\n\n return err(createError('TIMEOUT', 'Onboarding timed out'));\n }\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceContextAuth,\n CrossDeviceContextRegistration,\n} from '../types';\nimport { createAuthenticationOptions, createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class CrossDeviceManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Initializes a cross-device authentication session.\n * Typically called by the desktop side to get a QR code URL.\n */\n async init(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceAuth();\n }\n\n /**\n * Initializes a cross-device registration session (create account via QR).\n * Typically called by the desktop side to get a QR code URL for new users.\n */\n async initRegistration(options: {\n externalUserId: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceRegistration(options);\n }\n\n /**\n * High-level helper to poll for session status until it is completed.\n * Typically called by the desktop side after showing the QR code.\n */\n async waitForSession(\n sessionId: string,\n signal?: AbortSignal\n ): Promise<Result<{ session_token: string; user_id: string }, TryMellonError>> {\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n const statusResult = await this.apiClient.getCrossDeviceStatus(sessionId);\n if (!statusResult.ok) return err(statusResult.error);\n\n if (statusResult.value.status === 'completed') {\n if (!statusResult.value.session_token || !statusResult.value.user_id) {\n return err(createError('UNKNOWN_ERROR', 'Missing data in completed session'));\n }\n return ok({\n session_token: statusResult.value.session_token,\n user_id: statusResult.value.user_id,\n });\n }\n\n // Wait with abort check\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n await new Promise((resolve) => {\n const timeout = setTimeout(() => {\n resolve(null);\n signal?.removeEventListener('abort', onAbort);\n }, POLL_INTERVAL_MS);\n\n const onAbort = () => {\n clearTimeout(timeout);\n resolve(null);\n };\n signal?.addEventListener('abort', onAbort);\n });\n\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n }\n\n return err(createError('TIMEOUT', 'Cross-device authentication timed out'));\n }\n\n /**\n * Approves a cross-device session.\n * Typically called by the mobile side after scanning a QR code.\n * Branches by context type: registration → credentials.create + verify-registration;\n * auth → credentials.get + verify.\n */\n async approve(sessionId: string): Promise<Result<void, TryMellonError>> {\n const contextResult = await this.apiClient.getCrossDeviceContext(sessionId);\n if (!contextResult.ok) return err(contextResult.error);\n\n const context = contextResult.value;\n\n if (context.type === 'registration') {\n return this.executeRegistrationApproval(sessionId, context);\n }\n return this.executeAuthApproval(sessionId, context);\n }\n\n /**\n * Executes the registration branch: create credential and verify-registration.\n */\n private async executeRegistrationApproval(\n sessionId: string,\n context: CrossDeviceContextRegistration\n ): Promise<Result<void, TryMellonError>> {\n const creationOptionsResult = createRegistrationOptions(context.options);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceRegistration({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n\n /**\n * Executes the auth branch: get credential and verify.\n */\n private async executeAuthApproval(\n sessionId: string,\n context: CrossDeviceContextAuth\n ): Promise<Result<void, TryMellonError>> {\n const requestOptionsResult = createAuthenticationOptions(context.options);\n if (!requestOptionsResult.ok) return err(requestOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.get(requestOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'get');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForAuth(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceAuth({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n}\n","import type { EventHandler, EventPayload, TryMellonEvent } from '../types';\n\nexport class EventEmitter {\n private handlers: Map<TryMellonEvent, Set<EventHandler>>;\n\n constructor() {\n this.handlers = new Map();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n let handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n handlersSet = new Set();\n this.handlers.set(event, handlersSet);\n }\n\n handlersSet.add(handler);\n\n return () => {\n this.off(event, handler);\n };\n }\n\n off(event: TryMellonEvent, handler: EventHandler): void {\n const handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n return;\n }\n handlersSet.delete(handler);\n if (handlersSet.size === 0) {\n this.handlers.delete(event);\n }\n }\n\n emit(event: TryMellonEvent, payload: EventPayload): void {\n const handlersSet = this.handlers.get(event);\n if (handlersSet) {\n handlersSet.forEach((handler) => {\n try {\n handler(payload);\n } catch {\n // Silently ignore handler errors to prevent one handler from breaking others\n // Handler errors are the responsibility of the handler implementation\n }\n });\n }\n }\n\n removeAllListeners(): void {\n this.handlers.clear();\n }\n}\n","import { isWebAuthnSupported } from '../utils/support';\nimport { mapWebAuthnError, createNotSupportedError, createInvalidArgumentError } from '../errors';\nimport { validateCredentialStructure } from '../utils/validation';\nimport type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type { RecoverAccountOptions, RecoverAccountResult, RegisterStartResponse } from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { createRegistrationOptions } from './webauthn';\n\n/**\n * Recovers an account using an email OTP and creates a new passkey credential.\n * Manages the complete orchestrated WebAuthn registration flow for recovery.\n */\nexport async function recoverAccount(\n options: RecoverAccountOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RecoverAccountResult, TryMellonError>> {\n try {\n eventEmitter.emit('start', { type: 'start', operation: 'register' });\n\n if (!isWebAuthnSupported()) {\n const error = createNotSupportedError();\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n const extId = options.externalUserId ?? options.external_user_id;\n\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n if (!options.otp || typeof options.otp !== 'string' || options.otp.trim().length !== 6) {\n const error = createInvalidArgumentError('otp', 'must be a 6-digit string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 1. Verify OTP and get challenge from server\n const verifyResult = await apiClient.verifyAccountRecoveryOtp(extId, options.otp);\n\n if (!verifyResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: verifyResult.error });\n return err(verifyResult.error);\n }\n\n // 2. Create credential creation options for device rotation\n // Note: TypeScript expects a specific structure for challenge but our API returns Record<string, unknown>\n // We cast it to the correct shape expected by createRegistrationOptions\n const creationOptionsResult = createRegistrationOptions(\n verifyResult.value.challenge as RegisterStartResponse['challenge']\n );\n\n if (!creationOptionsResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: creationOptionsResult.error });\n return err(creationOptionsResult.error);\n }\n\n const creationOptions = {\n ...creationOptionsResult.value,\n };\n\n // 3. Request navigator to create the credential\n const credential = (await navigator.credentials.create(creationOptions)) as PublicKeyCredential;\n\n if (!credential) {\n const error = createInvalidArgumentError('credential', 'creation failed');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n try {\n validateCredentialStructure(credential);\n } catch (e) {\n const error = mapWebAuthnError(e);\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 4. Complete recovery and save the new credential in the server\n const finishResult = await apiClient.completeAccountRecovery(\n verifyResult.value.recovery_session_id,\n serializeCredentialForRegister(credential)\n );\n\n if (!finishResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: finishResult.error });\n return err(finishResult.error);\n }\n\n const result: RecoverAccountResult = {\n success: true,\n credentialId: finishResult.value.credential_id,\n status: finishResult.value.status,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n };\n\n eventEmitter.emit('success', { type: 'success', operation: 'register' });\n return ok(result);\n } catch (error) {\n const tryMellonError = mapWebAuthnError(error);\n eventEmitter.emit('error', { type: 'error', error: tryMellonError });\n return err(tryMellonError);\n }\n}\n","export const COSE_ALGORITHM_ES256 = -7;\nexport const COSE_ALGORITHM_RS256 = -257;\n\nexport const DEFAULT_API_BASE_URL = 'https://api.trymellonauth.com';\nexport const DEFAULT_TELEMETRY_ENDPOINT = 'https://api.trymellonauth.com/v1/telemetry';\nexport const DEFAULT_TIMEOUT_MS = 30000;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const DEFAULT_RETRY_DELAY_MS = 1000;\n\nexport const MIN_TIMEOUT_MS = 1000;\nexport const MAX_TIMEOUT_MS = 300000;\nexport const MIN_MAX_RETRIES = 0;\nexport const MAX_MAX_RETRIES = 10;\nexport const MIN_RETRY_DELAY_MS = 100;\nexport const MAX_RETRY_DELAY_MS = 10000;\n\n/**\n * Fixed session token returned by register() and authenticate() when sandbox mode is enabled.\n * Backends MUST NOT accept this token in production; only in development for testing the integration flow.\n */\nexport const SANDBOX_SESSION_TOKEN = 'trymellon_sandbox_session_token_v1';\n","import type { TelemetrySender, TelemetryPayload } from '../ports/telemetry';\n\n/**\n * Default telemetry sender: sends payload via sendBeacon (or fetch) to the given endpoint.\n * No retries; fire-and-forget.\n */\nexport function createDefaultTelemetrySender(endpoint: string): TelemetrySender {\n return {\n async send(payload: TelemetryPayload): Promise<void> {\n const body = JSON.stringify(payload);\n if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {\n navigator.sendBeacon(endpoint, body);\n return;\n }\n if (typeof fetch !== 'undefined') {\n await fetch(endpoint, {\n method: 'POST',\n body,\n headers: { 'Content-Type': 'application/json' },\n keepalive: true,\n });\n }\n },\n };\n}\n","export type TelemetryEvent = 'register' | 'authenticate';\n\nexport type TelemetryPayload = {\n event: TelemetryEvent;\n latencyMs: number;\n ok: true;\n};\n\nexport interface TelemetrySender {\n send(payload: TelemetryPayload): Promise<void>;\n}\n\n/**\n * Builds the minimal telemetry payload (no PII).\n */\nexport function buildTelemetryPayload(event: TelemetryEvent, latencyMs: number): TelemetryPayload {\n return { event, latencyMs, ok: true };\n}\n","import { ApiClient } from './api';\nimport { FetchHttpClient } from './fetch-client';\nimport { OnboardingManager } from './onboarding-manager';\nimport { CrossDeviceManager } from './cross-device-manager';\nimport { EventEmitter } from './events';\nimport { registerPasskey, authenticatePasskey } from './webauthn';\nimport { recoverAccount } from './recover';\nimport { isWebAuthnSupported, getClientStatus } from '../utils/support';\nimport { validateUrl, validateRange, createInvalidArgumentError } from '../errors';\nimport {\n DEFAULT_API_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_RETRY_DELAY_MS,\n DEFAULT_TELEMETRY_ENDPOINT,\n MIN_TIMEOUT_MS,\n MAX_TIMEOUT_MS,\n MIN_MAX_RETRIES,\n MAX_MAX_RETRIES,\n MIN_RETRY_DELAY_MS,\n MAX_RETRY_DELAY_MS,\n SANDBOX_SESSION_TOKEN,\n} from './constants';\nimport { createDefaultTelemetrySender } from './adapters/telemetry-sender';\nimport { buildTelemetryPayload, type TelemetrySender } from './ports/telemetry';\nimport type {\n TryMellonConfig,\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n ClientStatus,\n TryMellonEvent,\n EventHandler,\n EmailFallbackStartOptions,\n EmailFallbackVerifyOptions,\n EmailFallbackVerifyResult,\n SessionValidateResponse,\n RecoverAccountOptions,\n} from '../types';\nimport { ok, err, type Result } from '../utils/result';\nimport { type TryMellonError, isTryMellonError } from '../errors';\n\ndeclare const __VERSION__: string;\n\nexport class TryMellon {\n private readonly sandbox: boolean;\n private readonly sandboxToken: string;\n private apiClient: ApiClient;\n private eventEmitter: EventEmitter;\n private telemetrySender: TelemetrySender | undefined;\n private crossDeviceManager: CrossDeviceManager;\n public onboarding: OnboardingManager;\n\n /**\n * Configura una nueva instancia de TryMellon.\n * Valida la configuración y retorna un Result.\n * @param config Configuración del SDK\n */\n static create(config: TryMellonConfig): Result<TryMellon, TryMellonError> {\n try {\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n return err(createInvalidArgumentError('appId', 'must be a non-empty string'));\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n return err(createInvalidArgumentError('publishableKey', 'must be a non-empty string'));\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n // Safe to instantiate now\n return ok(new TryMellon(config));\n } catch (e) {\n if (isTryMellonError(e)) {\n return err(e);\n }\n return err(createInvalidArgumentError('config', (e as Error).message));\n }\n }\n\n /**\n * @deprecated Use `TryMellon.create(config)` instead to handle validation errors safely.\n * This constructor will throw errors if configuration is invalid.\n */\n constructor(config: TryMellonConfig) {\n this.sandbox = config.sandbox === true;\n this.sandboxToken =\n this.sandbox && config.sandboxToken != null && config.sandboxToken !== ''\n ? config.sandboxToken\n : SANDBOX_SESSION_TOKEN;\n\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n // Legacy validation for direct constructor usage (still throws to maintain behavior for legacy code,\n // but create() handles this safely before calling constructor)\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n throw createInvalidArgumentError('appId', 'must be a non-empty string');\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n throw createInvalidArgumentError('publishableKey', 'must be a non-empty string');\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n // validateUrl throws, which is expected for the constructor. create() catches it.\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const httpClient = new FetchHttpClient(timeoutMs, maxRetries, retryDelayMs, config.logger);\n\n const originHeader =\n config.origin ??\n (typeof window !== 'undefined' && window?.location?.origin\n ? window.location.origin\n : undefined);\n\n const defaultHeaders: Record<string, string> = {\n 'X-App-Id': appId.trim(),\n Authorization: `Bearer ${publishableKey.trim()}`,\n ...(originHeader && { Origin: originHeader }),\n };\n\n this.apiClient = new ApiClient(httpClient, apiBaseUrl, defaultHeaders);\n this.onboarding = new OnboardingManager(this.apiClient);\n this.crossDeviceManager = new CrossDeviceManager(this.apiClient);\n this.eventEmitter = new EventEmitter();\n\n if (config.enableTelemetry) {\n this.telemetrySender =\n config.telemetrySender ??\n createDefaultTelemetrySender(config.telemetryEndpoint ?? DEFAULT_TELEMETRY_ENDPOINT);\n }\n }\n\n static isSupported(): boolean {\n return isWebAuthnSupported();\n }\n\n async register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>> {\n if (this.sandbox) {\n const externalUserId =\n options.externalUserId ??\n (options as { external_user_id?: string }).external_user_id ??\n 'sandbox';\n return Promise.resolve(\n ok({\n success: true,\n credentialId: '',\n status: 'sandbox',\n sessionToken: this.sandboxToken,\n user: {\n userId: 'sandbox-user',\n externalUserId: typeof externalUserId === 'string' ? externalUserId : 'sandbox',\n },\n })\n );\n }\n const start = Date.now();\n const result = await registerPasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('register', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n\n async authenticate(\n options: AuthenticateOptions\n ): Promise<Result<AuthenticateResult, TryMellonError>> {\n if (this.sandbox) {\n const externalUserId =\n options.externalUserId ??\n (options as { external_user_id?: string }).external_user_id ??\n 'sandbox';\n return Promise.resolve(\n ok({\n authenticated: true,\n sessionToken: this.sandboxToken,\n user: {\n userId: 'sandbox-user',\n externalUserId: typeof externalUserId === 'string' ? externalUserId : 'sandbox',\n },\n })\n );\n }\n const start = Date.now();\n const result = await authenticatePasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('authenticate', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n if (this.sandbox && sessionToken === this.sandboxToken) {\n return Promise.resolve(\n ok({\n valid: true,\n user_id: 'sandbox-user',\n external_user_id: 'sandbox',\n tenant_id: 'sandbox-tenant',\n app_id: 'sandbox-app',\n })\n );\n }\n return this.apiClient.validateSession(sessionToken);\n }\n\n async getStatus(): Promise<ClientStatus> {\n return getClientStatus();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n return this.eventEmitter.on(event, handler);\n }\n\n version(): string {\n return typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0';\n }\n\n fallback = {\n email: {\n start: async (options: EmailFallbackStartOptions): Promise<Result<void, TryMellonError>> => {\n return this.apiClient.startEmailFallback(options);\n },\n verify: async (\n options: EmailFallbackVerifyOptions\n ): Promise<Result<EmailFallbackVerifyResult, TryMellonError>> => {\n return this.apiClient.verifyEmailCode(options.userId, options.code);\n },\n },\n };\n\n auth = {\n crossDevice: {\n init: () => this.crossDeviceManager.init(),\n initRegistration: (options: { externalUserId: string }) =>\n this.crossDeviceManager.initRegistration(options),\n waitForSession: (sessionId: string, signal?: AbortSignal) =>\n this.crossDeviceManager.waitForSession(sessionId, signal),\n approve: (sessionId: string) => this.crossDeviceManager.approve(sessionId),\n },\n recoverAccount: async (options: RecoverAccountOptions) => {\n return recoverAccount(options, this.apiClient, this.eventEmitter);\n },\n };\n}\n"],"mappings":"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","names":["angular_exports","__export","TRYMELLON_CONFIG","TryMellonService","provideTryMellonConfig","__toCommonJS","import_core","ok","value","err","error","TryMellonError","_TryMellonError","code","message","details","DEFAULT_MESSAGES","createError","isTryMellonError","error","createNotSupportedError","createInvalidArgumentError","field","reason","createError","createCredentialError","operation","createEncodingError","type","validateUrl","url","fieldName","urlObj","createInvalidArgumentError","error","isTryMellonError","validateRange","value","min","max","validateBase64Url","s","DOM_EXCEPTION_ERROR_MAP","mapWebAuthnError","name","message","errorCode","createError","isObject","value","isString","isNumber","isBoolean","isArray","validationError","message","details","err","createError","required","obj","key","validateRegisterStartResponse","data","isObject","validationError","session_id","required","isString","challenge","rp","user","challengeStr","pubKeyCredParams","isArray","item","isNumber","timeout","excludeCredentials","c","authenticatorSelection","ok","validateAuthStartResponse","ch","rpId","allowCredentials","userVerification","validateRegisterFinishResponse","credential_id","status","session_token","userId","externalUserId","email","metadata","validateAuthFinishResponse","authenticated","signals","isBoolean","validateSessionValidateResponse","data","isObject","validationError","valid","required","user_id","external_user_id","tenant_id","app_id","isBoolean","isString","ok","validateEmailVerifyResponse","data","isObject","validationError","sessionToken","required","isString","ok","ONBOARDING_STATUSES","REGISTER_PASSKEY_STATUSES","validateOnboardingStartResponse","data","isObject","validationError","session_id","required","onboarding_url","expires_in","isString","isNumber","ok","validateOnboardingStatusResponse","status","validateOnboardingRegisterResponse","challenge","parsedChallenge","chResult","validateOnboardingChallenge","rp","user","challengeStr","pubKeyCredParams","isArray","item","validateOnboardingRegisterPasskeyResponse","user_id","tenant_id","validateOnboardingCompleteResponse","session_token","isCreationOptionsShape","opts","o","isRequestOptionsShape","validateCrossDeviceInitResponse","data","isObject","validationError","session_id","qr_url","expires_at","isString","ok","validateCrossDeviceStatusResponse","status","validateCrossDeviceContextResponse","rawType","type","options","validateRecoveryVerifyResponse","data","isObject","validationError","challenge","required","recovery_session_id","isString","ok","validateRecoveryCompleteResponse","status","session_token","user","credential_id","user_id","userObj","ApiClient","httpClient","baseUrl","defaultHeaders","extra","path","body","validate","url","result","err","headers","request","validateRegisterStartResponse","validateAuthStartResponse","validateRegisterFinishResponse","validateAuthFinishResponse","sessionToken","validateSessionValidateResponse","options","ok","userId","code","validateEmailVerifyResponse","validateOnboardingStartResponse","sessionId","validateOnboardingStatusResponse","validateOnboardingRegisterResponse","validateOnboardingRegisterPasskeyResponse","validateOnboardingCompleteResponse","validateCrossDeviceInitResponse","validateCrossDeviceStatusResponse","validateCrossDeviceContextResponse","externalUserId","otp","validateRecoveryVerifyResponse","recoverySessionId","credential","validateRecoveryCompleteResponse","RETRY_DELAY_CAP_MS","generateRequestId","getRetryDelayMs","attempt","baseMs","delay","shouldRetryOnStatus","method","status","FetchHttpClient","timeoutMs","maxRetries","retryDelayMs","logger","url","headers","body","config","requestId","lastError","controller","timeoutId","response","errorData","message","rawCode","errResult","createError","resolve","err","ok","data","error","isWebAuthnSupported","isPlatformAuthenticatorAvailable","getClientStatus","isPasskeySupported","platformAuthenticatorAvailable","base64UrlEncode","buf","bytes","binary","b","createEncodingError","base64UrlDecode","s","base64","padding","padded","c","base64UrlDecodeToArrayBuffer","buffer","validateCredentialStructure","credential","operation","createCredentialError","isValidCredentialResponse","response","serializeCredentialForRegister","credential","createError","clientDataJSON","attestationObject","base64UrlEncode","serializeCredentialForAuth","authenticatorData","signature","userHandle","createRegistrationOptions","challenge","authenticatorType","validateBase64Url","challengeBuffer","base64UrlDecodeToArrayBuffer","userIdBuffer","authenticatorSelection","publicKey","cred","ok","e","err","mapWebAuthnError","createAuthenticationOptions","mediation","registerPasskey","options","apiClient","eventEmitter","isWebAuthnSupported","error","createNotSupportedError","extId","createInvalidArgumentError","startResult","creationOptionsResult","creationOptions","credential","validateCredentialStructure","finishResult","serializeCredentialForRegister","result","tryMellonError","authenticatePasskey","hasUserId","requestOptionsResult","requestOptions","serializeCredentialForAuth","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","OnboardingManager","apiClient","options","startResult","err","session_id","attempt","resolve","statusResult","status","onboarding_url","registerInfoResult","registerInfo","createError","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","registerPasskeyResult","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","CrossDeviceManager","apiClient","options","sessionId","signal","attempt","err","createError","statusResult","ok","resolve","timeout","onAbort","contextResult","context","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","requestOptionsResult","createAuthenticationOptions","serializeCredentialForAuth","EventEmitter","event","handler","handlersSet","payload","recoverAccount","options","apiClient","eventEmitter","isWebAuthnSupported","error","createNotSupportedError","err","extId","createInvalidArgumentError","verifyResult","creationOptionsResult","createRegistrationOptions","creationOptions","credential","validateCredentialStructure","e","mapWebAuthnError","finishResult","serializeCredentialForRegister","result","ok","tryMellonError","DEFAULT_API_BASE_URL","DEFAULT_TELEMETRY_ENDPOINT","SANDBOX_SESSION_TOKEN","createDefaultTelemetrySender","endpoint","payload","body","buildTelemetryPayload","event","latencyMs","TryMellon","_TryMellon","config","appId","publishableKey","err","createInvalidArgumentError","apiBaseUrl","DEFAULT_API_BASE_URL","validateUrl","timeoutMs","validateRange","ok","e","isTryMellonError","SANDBOX_SESSION_TOKEN","maxRetries","retryDelayMs","httpClient","FetchHttpClient","originHeader","defaultHeaders","ApiClient","OnboardingManager","CrossDeviceManager","EventEmitter","createDefaultTelemetrySender","DEFAULT_TELEMETRY_ENDPOINT","isWebAuthnSupported","options","externalUserId","start","result","registerPasskey","buildTelemetryPayload","authenticatePasskey","sessionToken","getClientStatus","event","handler","sessionId","signal","recoverAccount","TRYMELLON_CONFIG","_TryMellonService_decorators","_init","TryMellonService","TryMellon","__decoratorStart","__decorateElement","__runInitializers","provideTryMellonConfig","config","TRYMELLON_CONFIG"]}
1
+ {"version":3,"sources":["../src/angular/index.ts","../src/angular/trymellon.service.ts","../src/utils/result.ts","../src/errors.ts","../src/core/validators/helpers.ts","../src/core/validators/register-auth.ts","../src/core/validators/session.ts","../src/core/validators/email.ts","../src/core/validators/onboarding.ts","../src/core/validators/cross-device.ts","../src/core/validators/recovery.ts","../src/core/api.ts","../src/core/fetch-client.ts","../src/utils/base64url.ts","../src/core/webauthn-utils.ts","../src/utils/support.ts","../src/utils/validation.ts","../src/core/ceremony.ts","../src/core/webauthn.ts","../src/core/onboarding-manager.ts","../src/core/cross-device-manager.ts","../src/core/events.ts","../src/core/recover.ts","../src/core/constants.ts","../src/core/adapters/telemetry-sender.ts","../src/core/ports/telemetry.ts","../src/core/trymellon.ts"],"sourcesContent":["import type { Provider } from '@angular/core';\nimport type { TryMellonConfig } from '../types';\nimport { TRYMELLON_CONFIG } from './trymellon.service';\n\nexport { TryMellonService, TRYMELLON_CONFIG } from './trymellon.service';\n\nexport function provideTryMellonConfig(config: TryMellonConfig): Provider {\n return { provide: TRYMELLON_CONFIG, useValue: config } as Provider;\n}\n","import { Injectable, InjectionToken, inject } from '@angular/core';\nimport { TryMellon } from '../core/trymellon';\nimport type { TryMellonConfig } from '../types';\n\nexport const TRYMELLON_CONFIG = new InjectionToken<TryMellonConfig>('TRYMELLON_CONFIG');\n\n@Injectable({ providedIn: 'root' })\nexport class TryMellonService {\n private readonly config = inject(TRYMELLON_CONFIG, { optional: true });\n private _client: TryMellon | null = null;\n\n get client(): TryMellon {\n if (this._client == null) {\n if (this.config == null) {\n throw new Error(\n 'TryMellonService: provide TRYMELLON_CONFIG (e.g. via provideTryMellonConfig(config))'\n );\n }\n this._client = new TryMellon(this.config);\n }\n return this._client;\n }\n}\n","export type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };\n\nexport const ok = <T>(value: T): Result<T, never> => ({ ok: true, value });\nexport const err = <E>(error: E): Result<never, E> => ({ ok: false, error });\n\nexport function map<T, E, U>(result: Result<T, E>, mapper: (value: T) => U): Result<U, E> {\n if (result.ok) {\n return ok(mapper(result.value));\n }\n return result;\n}\n\nexport function mapErr<T, E, F>(result: Result<T, E>, mapper: (error: E) => F): Result<T, F> {\n if (!result.ok) {\n return err(mapper(result.error));\n }\n return result;\n}\n\nexport function unwrap<T, E>(result: Result<T, E>): T {\n if (result.ok) {\n return result.value;\n }\n throw result.error;\n}\n","export type TryMellonErrorCode =\n | 'NOT_SUPPORTED'\n | 'USER_CANCELLED'\n | 'PASSKEY_NOT_FOUND'\n | 'SESSION_EXPIRED'\n | 'NETWORK_FAILURE'\n | 'INVALID_ARGUMENT'\n | 'TIMEOUT'\n | 'ABORTED'\n | 'ABORT_ERROR'\n | 'CHALLENGE_MISMATCH'\n | 'UNKNOWN_ERROR';\n\nexport class TryMellonError extends Error {\n readonly code: TryMellonErrorCode;\n readonly details?: unknown;\n readonly isTryMellonError = true;\n\n constructor(code: TryMellonErrorCode, message: string, details?: unknown) {\n super(message);\n this.name = 'TryMellonError';\n this.code = code;\n this.details = details;\n\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, TryMellonError);\n }\n }\n}\n\nconst DEFAULT_MESSAGES: Record<TryMellonErrorCode, string> = {\n NOT_SUPPORTED: 'WebAuthn is not supported in this environment',\n USER_CANCELLED: 'User cancelled the operation',\n PASSKEY_NOT_FOUND: 'Passkey not found',\n SESSION_EXPIRED: 'Session has expired',\n NETWORK_FAILURE: 'Network request failed',\n INVALID_ARGUMENT: 'Invalid argument provided',\n TIMEOUT: 'Operation timed out',\n ABORTED: 'Operation was aborted',\n ABORT_ERROR: 'Operation aborted by user or timeout',\n CHALLENGE_MISMATCH: 'This link was already used or expired. Please try again from your computer.',\n UNKNOWN_ERROR: 'An unknown error occurred',\n};\n\nexport function createError(\n code: TryMellonErrorCode,\n message?: string,\n details?: unknown\n): TryMellonError {\n return new TryMellonError(code, message ?? DEFAULT_MESSAGES[code], details);\n}\n\nexport function isTryMellonError(error: unknown): error is TryMellonError {\n return (\n error instanceof TryMellonError ||\n (typeof error === 'object' &&\n error !== null &&\n 'isTryMellonError' in error &&\n (error as TryMellonError).isTryMellonError === true)\n );\n}\n\nexport function createNotSupportedError(): TryMellonError {\n return createError('NOT_SUPPORTED');\n}\n\nexport function createUserCancelledError(): TryMellonError {\n return createError('USER_CANCELLED');\n}\n\nexport function createNetworkError(cause?: Error): TryMellonError {\n return createError('NETWORK_FAILURE', undefined, {\n cause: cause?.message,\n originalError: cause,\n });\n}\n\nexport function createTimeoutError(): TryMellonError {\n return createError('TIMEOUT');\n}\n\nexport function createInvalidArgumentError(field: string, reason: string): TryMellonError {\n return createError('INVALID_ARGUMENT', `Invalid argument: ${field} - ${reason}`, {\n field,\n reason,\n });\n}\n\nexport function createCredentialError(operation: 'create' | 'get'): TryMellonError {\n return createError('UNKNOWN_ERROR', `Failed to ${operation} credential`, { operation });\n}\n\nexport function createEncodingError(type: 'encode' | 'decode'): TryMellonError {\n return createError(\n 'NOT_SUPPORTED',\n `No base64 ${type === 'encode' ? 'encoding' : 'decoding'} available`,\n { type }\n );\n}\n\nexport function validateNonEmptyString(value: unknown, fieldName: string): asserts value is string {\n if (!value || typeof value !== 'string' || value.trim() === '') {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n}\n\nexport function validateUrl(url: string, fieldName: string): void {\n try {\n const urlObj = new URL(url);\n if (urlObj.protocol !== 'https:' && urlObj.protocol !== 'http:') {\n throw createInvalidArgumentError(fieldName, 'must use http or https protocol');\n }\n } catch (error) {\n if (isTryMellonError(error)) {\n throw error;\n }\n throw createInvalidArgumentError(fieldName, 'must be a valid URL');\n }\n}\n\nexport function validateRange(value: number, fieldName: string, min: number, max: number): void {\n if (!Number.isFinite(value)) {\n throw createInvalidArgumentError(fieldName, 'must be a finite number');\n }\n if (value < min || value > max) {\n throw createInvalidArgumentError(fieldName, `must be between ${min} and ${max}`);\n }\n}\n\nexport function validateBase64Url(s: string, fieldName: string): void {\n if (typeof s !== 'string' || s.length === 0) {\n throw createInvalidArgumentError(fieldName, 'must be a non-empty string');\n }\n if (!/^[A-Za-z0-9_-]+$/.test(s)) {\n throw createInvalidArgumentError(fieldName, 'must be a valid base64url string');\n }\n}\n\nconst DOM_EXCEPTION_ERROR_MAP: Record<string, TryMellonErrorCode> = {\n NotAllowedError: 'USER_CANCELLED',\n AbortError: 'ABORTED',\n NotSupportedError: 'NOT_SUPPORTED',\n SecurityError: 'NOT_SUPPORTED',\n InvalidStateError: 'UNKNOWN_ERROR',\n UnknownError: 'UNKNOWN_ERROR',\n};\n\nexport function mapWebAuthnError(error: unknown): TryMellonError {\n if (error instanceof DOMException) {\n const name = error.name;\n const message = error.message || 'WebAuthn operation failed';\n const errorCode = DOM_EXCEPTION_ERROR_MAP[name] ?? 'UNKNOWN_ERROR';\n return createError(errorCode, message, { originalError: error });\n }\n\n if (error instanceof Error) {\n return createError('UNKNOWN_ERROR', error.message, { originalError: error });\n }\n\n return createError('UNKNOWN_ERROR', 'An unknown error occurred', {\n originalError: error,\n });\n}\n","import { err, ok, type Result } from '../../utils/result';\nimport { createError, type TryMellonError } from '../../errors';\n\nexport function isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nexport function isString(value: unknown): value is string {\n return typeof value === 'string';\n}\n\nexport function isNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\nexport function isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n}\n\nexport function isArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\nexport function validationError(\n message: string,\n details?: { field?: string; expected?: string; originalData?: unknown }\n): Result<never, TryMellonError> {\n return err(\n createError('UNKNOWN_ERROR', message, {\n ...details,\n originalData: details?.originalData,\n })\n );\n}\n\nexport function required(obj: Record<string, unknown>, key: string): unknown {\n return obj[key];\n}\n\nexport function optionalString(obj: Record<string, unknown>, key: string): string | undefined {\n const v = obj[key];\n return v === undefined ? undefined : typeof v === 'string' ? v : undefined;\n}\n\n// DRY Helpers for common TryMellon objects\n\nexport function validateChallengeRP(rp: unknown, data: unknown): Result<true, TryMellonError> {\n if (!isObject(rp) || !isString(rp.name) || !isString(rp.id)) {\n return validationError('Invalid API response: challenge.rp must have name and id strings', {\n originalData: data,\n });\n }\n return ok(true);\n}\n\nexport function validateChallengeUser(user: unknown, data: unknown): Result<true, TryMellonError> {\n if (\n !isObject(user) ||\n !isString(user.id) ||\n !isString(user.name) ||\n !isString(user.displayName)\n ) {\n return validationError(\n 'Invalid API response: challenge.user must have id, name, displayName strings',\n { originalData: data }\n );\n }\n return ok(true);\n}\n\nexport function validatePubKeyCredParams(\n params: unknown,\n data: unknown\n): Result<true, TryMellonError> {\n if (!isArray(params)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of params) {\n if (!isObject(item) || item.type !== 'public-key' || !isNumber(item.alg)) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n { originalData: data }\n );\n }\n }\n return ok(true);\n}\n\nexport function validateUserEntity(\n user: unknown,\n data: unknown\n): Result<\n { user_id: string; external_user_id: string; email?: string; metadata?: Record<string, unknown> },\n TryMellonError\n> {\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const userId = required(user, 'user_id');\n const externalUserId = required(user, 'external_user_id');\n if (!isString(userId) || !isString(externalUserId)) {\n return validationError(\n 'Invalid API response: user must have user_id and external_user_id strings',\n { originalData: data }\n );\n }\n\n const email = user.email;\n const metadata = user.metadata;\n if (email !== undefined && !isString(email)) {\n return validationError('Invalid API response: user.email must be string', {\n originalData: data,\n });\n }\n if (metadata !== undefined && (typeof metadata !== 'object' || metadata === null)) {\n return validationError('Invalid API response: user.metadata must be object', {\n originalData: data,\n });\n }\n\n return ok({\n user_id: userId,\n external_user_id: externalUserId,\n ...(email !== undefined && { email }),\n ...(metadata !== undefined && { metadata: metadata as Record<string, unknown> }),\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n RegisterStartResponse,\n AuthStartResponse,\n RegisterFinishResponse,\n AuthFinishResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport {\n isObject,\n isString,\n isNumber,\n isBoolean,\n isArray,\n validationError,\n required,\n validateChallengeRP,\n validateChallengeUser,\n validatePubKeyCredParams,\n validateUserEntity,\n} from './helpers';\n\nexport function validateRegisterStartResponse(\n data: unknown\n): Result<RegisterStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const rpResult = validateChallengeRP(required(challenge, 'rp'), data);\n if (!rpResult.ok) return rpResult;\n\n const userResult = validateChallengeUser(required(challenge, 'user'), data);\n if (!userResult.ok) return userResult;\n\n const challengeStr = required(challenge, 'challenge');\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n\n const pubKeyCredParamsResult = validatePubKeyCredParams(\n required(challenge, 'pubKeyCredParams'),\n data\n );\n if (!pubKeyCredParamsResult.ok) return pubKeyCredParamsResult;\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const excludeCredentials = challenge.excludeCredentials;\n if (excludeCredentials !== undefined) {\n if (!isArray(excludeCredentials)) {\n return validationError('Invalid API response: excludeCredentials must be array', {\n originalData: data,\n });\n }\n for (const c of excludeCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: excludeCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const authenticatorSelection = challenge.authenticatorSelection;\n if (authenticatorSelection !== undefined && !isObject(authenticatorSelection)) {\n return validationError('Invalid API response: authenticatorSelection must be object', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n challenge: {\n rp: challenge.rp as RegisterStartResponse['challenge']['rp'],\n user: challenge.user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams:\n challenge.pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n ...(timeout !== undefined && { timeout }),\n ...(excludeCredentials !== undefined && {\n excludeCredentials:\n excludeCredentials as RegisterStartResponse['challenge']['excludeCredentials'],\n }),\n ...(authenticatorSelection !== undefined && {\n authenticatorSelection:\n authenticatorSelection as RegisterStartResponse['challenge']['authenticatorSelection'],\n }),\n },\n });\n}\n\nexport function validateAuthStartResponse(\n data: unknown\n): Result<AuthStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n\n const challenge = required(data, 'challenge');\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n const ch = required(challenge, 'challenge');\n const rpId = required(challenge, 'rpId');\n const allowCredentials = challenge.allowCredentials;\n if (!isString(ch)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isString(rpId)) {\n return validationError('Invalid API response: challenge.rpId must be string', {\n originalData: data,\n });\n }\n if (allowCredentials !== undefined && !isArray(allowCredentials)) {\n return validationError('Invalid API response: allowCredentials must be array', {\n originalData: data,\n });\n }\n if (allowCredentials) {\n for (const c of allowCredentials) {\n if (\n !isObject(c) ||\n (c as Record<string, unknown>).type !== 'public-key' ||\n !isString((c as Record<string, unknown>).id)\n ) {\n return validationError(\n 'Invalid API response: allowCredentials items must have id and type',\n {\n originalData: data,\n }\n );\n }\n }\n }\n\n const timeout = challenge.timeout;\n if (timeout !== undefined && !isNumber(timeout)) {\n return validationError('Invalid API response: challenge.timeout must be number', {\n originalData: data,\n });\n }\n\n const userVerification = challenge.userVerification;\n if (\n userVerification !== undefined &&\n !['required', 'preferred', 'discouraged'].includes(String(userVerification))\n ) {\n return validationError(\n 'Invalid API response: userVerification must be required|preferred|discouraged',\n {\n originalData: data,\n }\n );\n }\n\n return ok({\n session_id,\n challenge: {\n challenge: ch,\n rpId,\n allowCredentials:\n (allowCredentials as AuthStartResponse['challenge']['allowCredentials']) ?? [],\n ...(timeout !== undefined && { timeout }),\n ...(userVerification !== undefined && {\n userVerification: userVerification as AuthStartResponse['challenge']['userVerification'],\n }),\n },\n });\n}\n\nexport function validateRegisterFinishResponse(\n data: unknown\n): Result<RegisterFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const credential_id = required(data, 'credential_id');\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n const userResult = validateUserEntity(user, data);\n if (!userResult.ok) return validationError(userResult.error.message, { originalData: data });\n\n return ok({\n credential_id,\n status,\n session_token,\n user: userResult.value,\n });\n}\n\nexport function validateAuthFinishResponse(\n data: unknown\n): Result<AuthFinishResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const authenticated = required(data, 'authenticated');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const signals = required(data, 'signals');\n\n if (!isBoolean(authenticated)) {\n return validationError('Invalid API response: authenticated must be boolean', {\n field: 'authenticated',\n originalData: data,\n });\n }\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n const userResult = validateUserEntity(user, data);\n if (!userResult.ok) return validationError(userResult.error.message, { originalData: data });\n\n if (signals !== undefined && !isObject(signals)) {\n return validationError('Invalid API response: signals must be object', {\n originalData: data,\n });\n }\n\n return ok({\n authenticated,\n session_token,\n user: userResult.value,\n signals: signals as AuthFinishResponse['signals'],\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { SessionValidateResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isBoolean, required, validationError } from './helpers';\n\nexport function validateSessionValidateResponse(\n data: unknown\n): Result<SessionValidateResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const valid = required(data, 'valid');\n const user_id = required(data, 'user_id');\n const external_user_id = required(data, 'external_user_id');\n const tenant_id = required(data, 'tenant_id');\n const app_id = required(data, 'app_id');\n\n if (!isBoolean(valid)) {\n return validationError('Invalid API response: valid must be boolean', {\n field: 'valid',\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n field: 'user_id',\n originalData: data,\n });\n }\n if (!isString(external_user_id)) {\n return validationError('Invalid API response: external_user_id must be string', {\n field: 'external_user_id',\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n field: 'tenant_id',\n originalData: data,\n });\n }\n if (!isString(app_id)) {\n return validationError('Invalid API response: app_id must be string', {\n field: 'app_id',\n originalData: data,\n });\n }\n\n return ok({\n valid,\n user_id,\n external_user_id,\n tenant_id,\n app_id,\n });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, required, validationError } from './helpers';\n\nexport function validateEmailVerifyResponse(\n data: unknown\n): Result<{ sessionToken: string }, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const sessionToken = required(data, 'sessionToken');\n if (!isString(sessionToken)) {\n return validationError('Invalid API response: sessionToken must be string', {\n field: 'sessionToken',\n originalData: data,\n });\n }\n\n return ok({ sessionToken });\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type {\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterResponse,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteResponse,\n RegisterStartResponse,\n} from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, isNumber, isArray, required, validationError } from './helpers';\n\nconst ONBOARDING_STATUSES = ['pending_passkey', 'pending_data', 'completed'] as const;\nconst REGISTER_PASSKEY_STATUSES = ['pending_data', 'completed'] as const;\n\nexport function validateOnboardingStartResponse(\n data: unknown\n): Result<OnboardingStartResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n field: 'onboarding_url',\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n field: 'expires_in',\n originalData: data,\n });\n }\n\n return ok({ session_id, onboarding_url, expires_in });\n}\n\nexport function validateOnboardingStatusResponse(\n data: unknown\n): Result<OnboardingStatusResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n const expires_in = required(data, 'expires_in');\n\n if (\n !isString(status) ||\n !ONBOARDING_STATUSES.includes(status as (typeof ONBOARDING_STATUSES)[number])\n ) {\n return validationError(\n 'Invalid API response: status must be pending_passkey|pending_data|completed',\n {\n field: 'status',\n originalData: data,\n }\n );\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n if (!isNumber(expires_in)) {\n return validationError('Invalid API response: expires_in must be number', {\n originalData: data,\n });\n }\n\n return ok({\n status: status as OnboardingStatusResponse['status'],\n onboarding_url,\n expires_in,\n });\n}\n\n/** Response may include optional challenge for same-device passkey registration */\nexport type OnboardingRegisterResponseWithChallenge = OnboardingRegisterResponse & {\n challenge?: RegisterStartResponse['challenge'];\n};\n\nexport function validateOnboardingRegisterResponse(\n data: unknown\n): Result<OnboardingRegisterResponseWithChallenge, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const onboarding_url = required(data, 'onboarding_url');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n field: 'session_id',\n originalData: data,\n });\n }\n if (status !== 'pending_passkey') {\n return validationError('Invalid API response: status must be pending_passkey', {\n field: 'status',\n originalData: data,\n });\n }\n if (!isString(onboarding_url)) {\n return validationError('Invalid API response: onboarding_url must be string', {\n originalData: data,\n });\n }\n\n const challenge = data.challenge;\n let parsedChallenge: RegisterStartResponse['challenge'] | undefined;\n if (challenge !== undefined) {\n const chResult = validateOnboardingChallenge(challenge);\n if (!chResult.ok) return chResult;\n parsedChallenge = chResult.value;\n }\n\n return ok({\n session_id,\n status: 'pending_passkey',\n onboarding_url,\n ...(parsedChallenge !== undefined && { challenge: parsedChallenge }),\n });\n}\n\nfunction validateOnboardingChallenge(\n data: unknown\n): Result<RegisterStartResponse['challenge'], TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: challenge must be object', {\n originalData: data,\n });\n }\n\n const rp = required(data, 'rp');\n const user = required(data, 'user');\n const challengeStr = required(data, 'challenge');\n const pubKeyCredParams = required(data, 'pubKeyCredParams');\n\n if (\n !isObject(rp) ||\n !isString((rp as Record<string, unknown>).name) ||\n !isString((rp as Record<string, unknown>).id)\n ) {\n return validationError('Invalid API response: challenge.rp must have name and id', {\n originalData: data,\n });\n }\n if (\n !isObject(user) ||\n !isString((user as Record<string, unknown>).id) ||\n !isString((user as Record<string, unknown>).name) ||\n !isString((user as Record<string, unknown>).displayName)\n ) {\n return validationError('Invalid API response: challenge.user must have id, name, displayName', {\n originalData: data,\n });\n }\n if (!isString(challengeStr)) {\n return validationError('Invalid API response: challenge.challenge must be string', {\n originalData: data,\n });\n }\n if (!isArray(pubKeyCredParams)) {\n return validationError('Invalid API response: challenge.pubKeyCredParams must be array', {\n originalData: data,\n });\n }\n for (const item of pubKeyCredParams) {\n if (\n !isObject(item) ||\n (item as Record<string, unknown>).type !== 'public-key' ||\n !isNumber((item as Record<string, unknown>).alg)\n ) {\n return validationError(\n 'Invalid API response: pubKeyCredParams items must have type and alg',\n {\n originalData: data,\n }\n );\n }\n }\n\n return ok({\n rp: rp as RegisterStartResponse['challenge']['rp'],\n user: user as RegisterStartResponse['challenge']['user'],\n challenge: challengeStr,\n pubKeyCredParams: pubKeyCredParams as RegisterStartResponse['challenge']['pubKeyCredParams'],\n });\n}\n\nexport function validateOnboardingRegisterPasskeyResponse(\n data: unknown\n): Result<OnboardingRegisterPasskeyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (\n !isString(status) ||\n !REGISTER_PASSKEY_STATUSES.includes(status as (typeof REGISTER_PASSKEY_STATUSES)[number])\n ) {\n return validationError('Invalid API response: status must be pending_data|completed', {\n originalData: data,\n });\n }\n if (!isString(user_id)) {\n return validationError('Invalid API response: user_id must be string', {\n originalData: data,\n });\n }\n if (!isString(tenant_id)) {\n return validationError('Invalid API response: tenant_id must be string', {\n originalData: data,\n });\n }\n\n return ok({\n session_id,\n status: status as OnboardingRegisterPasskeyResponse['status'],\n user_id,\n tenant_id,\n });\n}\n\nexport function validateOnboardingCompleteResponse(\n data: unknown\n): Result<OnboardingCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = required(data, 'session_id');\n const status = required(data, 'status');\n const user_id = required(data, 'user_id');\n const tenant_id = required(data, 'tenant_id');\n const session_token = required(data, 'session_token');\n\n if (!isString(session_id)) {\n return validationError('Invalid API response: session_id must be string', {\n originalData: data,\n });\n }\n if (status !== 'completed') {\n return validationError('Invalid API response: status must be completed', {\n originalData: data,\n });\n }\n if (!isString(user_id) || !isString(tenant_id) || !isString(session_token)) {\n return validationError(\n 'Invalid API response: user_id, tenant_id, session_token must be strings',\n { originalData: data }\n );\n }\n\n return ok({\n session_id,\n status: 'completed',\n user_id,\n tenant_id,\n session_token,\n });\n}\n","import { ok } from '../../utils/result';\nimport type { Result } from '../../utils/result';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, validationError } from './helpers';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n} from '../../types';\n\nfunction isCreationOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return (\n typeof o.challenge === 'string' &&\n o.rp != null &&\n typeof o.rp === 'object' &&\n o.user != null &&\n typeof o.user === 'object' &&\n Array.isArray((o as { pubKeyCredParams?: unknown }).pubKeyCredParams)\n );\n}\n\nfunction isRequestOptionsShape(opts: unknown): opts is Record<string, unknown> {\n if (!opts || typeof opts !== 'object') return false;\n const o = opts as Record<string, unknown>;\n return typeof o.challenge === 'string' && typeof o.rpId === 'string';\n}\n\nexport function validateCrossDeviceInitResponse(\n data: unknown\n): Result<CrossDeviceInitResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const session_id = data.session_id;\n const qr_url = data.qr_url;\n const expires_at = data.expires_at;\n\n if (!isString(session_id) || !isString(qr_url) || !isString(expires_at)) {\n return validationError('Invalid API response: missing required fields', { originalData: data });\n }\n\n return ok({\n session_id,\n qr_url,\n expires_at,\n });\n}\n\nexport function validateCrossDeviceStatusResponse(\n data: unknown\n): Result<CrossDeviceStatusResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = data.status;\n if (!isString(status) || !['pending', 'authenticated', 'completed'].includes(status)) {\n return validationError('Invalid API response: invalid status', { originalData: data });\n }\n\n return ok({\n status: status as CrossDeviceStatusResult['status'],\n user_id: data.user_id as string | undefined,\n session_token: data.session_token as string | undefined,\n });\n}\n\nexport function validateCrossDeviceContextResponse(\n data: unknown\n): Result<CrossDeviceContextResult, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const rawType = data.type;\n const type =\n rawType === 'registration' ? 'registration' : rawType === 'auth' ? 'auth' : ('auth' as const);\n\n const options = data.options;\n if (!isObject(options)) {\n return validationError('Invalid API response: options are required', { originalData: data });\n }\n\n if (type === 'registration') {\n if (!isCreationOptionsShape(options)) {\n return validationError(\n 'Invalid API response: registration options must have challenge, rp, user, pubKeyCredParams',\n { originalData: data }\n );\n }\n return ok({\n type: 'registration',\n options,\n } as CrossDeviceContextResult);\n }\n\n if (!isRequestOptionsShape(options)) {\n return validationError('Invalid API response: auth options must have challenge and rpId', {\n originalData: data,\n });\n }\n return ok({ type: 'auth', options } as CrossDeviceContextResult);\n}\n","import type { Result } from '../../utils/result';\nimport { ok } from '../../utils/result';\nimport type { RecoveryVerifyResponse, RecoveryCompleteResponse } from '../../types';\nimport type { TryMellonError } from '../../errors';\nimport { isObject, isString, required, validationError } from './helpers';\n\nexport function validateRecoveryVerifyResponse(\n data: unknown\n): Result<RecoveryVerifyResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const challenge = required(data, 'challenge');\n const recovery_session_id = required(data, 'recovery_session_id');\n\n if (!isObject(challenge)) {\n return validationError('Invalid API response: challenge must be object', {\n field: 'challenge',\n originalData: data,\n });\n }\n\n if (!isString(recovery_session_id)) {\n return validationError('Invalid API response: recovery_session_id must be string', {\n field: 'recovery_session_id',\n originalData: data,\n });\n }\n\n return ok({\n challenge: challenge as Record<string, unknown>,\n recovery_session_id,\n });\n}\n\nexport function validateRecoveryCompleteResponse(\n data: unknown\n): Result<RecoveryCompleteResponse, TryMellonError> {\n if (!isObject(data)) {\n return validationError('Invalid API response: expected object', { originalData: data });\n }\n\n const status = required(data, 'status');\n const session_token = required(data, 'session_token');\n const user = required(data, 'user');\n const credential_id = required(data, 'credential_id');\n\n if (!isString(status)) {\n return validationError('Invalid API response: status must be string', {\n field: 'status',\n originalData: data,\n });\n }\n\n if (!isString(session_token)) {\n return validationError('Invalid API response: session_token must be string', {\n field: 'session_token',\n originalData: data,\n });\n }\n\n if (!isString(credential_id)) {\n return validationError('Invalid API response: credential_id must be string', {\n field: 'credential_id',\n originalData: data,\n });\n }\n\n if (!isObject(user)) {\n return validationError('Invalid API response: user must be object', {\n field: 'user',\n originalData: data,\n });\n }\n\n const user_id = required(user, 'user_id');\n if (!isString(user_id)) {\n return validationError('Invalid API response: user.user_id must be string', {\n field: 'user.user_id',\n originalData: data,\n });\n }\n\n const userObj = user as Record<string, unknown>;\n return ok({\n status,\n session_token,\n credential_id,\n user: {\n user_id,\n external_user_id: isString(userObj.external_user_id) ? userObj.external_user_id : undefined,\n email: isString(userObj.email) ? userObj.email : undefined,\n metadata: isObject(userObj.metadata)\n ? (userObj.metadata as Record<string, unknown>)\n : undefined,\n },\n });\n}\n","import type { HttpClient } from './http-client';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport {\n validateRegisterStartResponse,\n validateAuthStartResponse,\n validateRegisterFinishResponse,\n validateAuthFinishResponse,\n validateSessionValidateResponse,\n validateEmailVerifyResponse,\n validateOnboardingStartResponse,\n validateOnboardingStatusResponse,\n validateOnboardingRegisterResponse,\n validateOnboardingRegisterPasskeyResponse,\n validateOnboardingCompleteResponse,\n validateCrossDeviceInitResponse,\n validateCrossDeviceStatusResponse,\n validateCrossDeviceContextResponse,\n validateRecoveryVerifyResponse,\n validateRecoveryCompleteResponse,\n} from './validators';\nimport type {\n RegisterStartRequest,\n RegisterStartResponse,\n AuthStartRequest,\n AuthStartResponse,\n RegisterFinishRequest,\n RegisterFinishResponse,\n AuthFinishRequest,\n AuthFinishResponse,\n SessionValidateResponse,\n OnboardingStartRequest,\n OnboardingStartResponse,\n OnboardingStatusResponse,\n OnboardingRegisterPasskeyRequest,\n OnboardingRegisterPasskeyResponse,\n OnboardingCompleteRequest,\n OnboardingCompleteResponse,\n CrossDeviceInitResult,\n CrossDeviceStatusResult,\n CrossDeviceContextResult,\n CrossDeviceVerifyRequest,\n CrossDeviceVerifyRegistrationRequest,\n RecoveryVerifyResponse,\n RecoveryCompleteResponse,\n} from '../types';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\n\nexport class ApiClient {\n constructor(\n private readonly httpClient: HttpClient,\n private readonly baseUrl: string,\n private readonly defaultHeaders: Record<string, string> = {}\n ) {}\n\n private mergeHeaders(extra?: Record<string, string>): Record<string, string> {\n return { ...this.defaultHeaders, ...extra };\n }\n\n private async post<Req, Res>(\n path: string,\n body: Req,\n validate: (data: unknown) => Result<Res, TryMellonError>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.post<unknown>(url, body, this.mergeHeaders());\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n private async get<Res>(\n path: string,\n validate: (data: unknown) => Result<Res, TryMellonError>,\n headers?: Record<string, string>\n ): Promise<Result<Res, TryMellonError>> {\n const url = `${this.baseUrl}${path}`;\n const result = await this.httpClient.get<unknown>(url, this.mergeHeaders(headers));\n\n if (!result.ok) {\n return err(result.error);\n }\n\n return validate(result.value);\n }\n\n async startRegister(\n request: RegisterStartRequest\n ): Promise<Result<RegisterStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/start', request, validateRegisterStartResponse);\n }\n\n async startAuth(request: AuthStartRequest): Promise<Result<AuthStartResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/start', request, validateAuthStartResponse);\n }\n\n async finishRegister(\n request: RegisterFinishRequest\n ): Promise<Result<RegisterFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/register/finish', request, validateRegisterFinishResponse);\n }\n\n async finishAuthentication(\n request: AuthFinishRequest\n ): Promise<Result<AuthFinishResponse, TryMellonError>> {\n return this.post('/v1/passkeys/auth/finish', request, validateAuthFinishResponse);\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n return this.get('/v1/sessions/validate', validateSessionValidateResponse, {\n Authorization: `Bearer ${sessionToken}`,\n });\n }\n\n async startEmailFallback(options: {\n userId: string;\n email: string;\n }): Promise<Result<void, TryMellonError>> {\n const url = `${this.baseUrl}/v1/fallback/email/start`;\n const result = await this.httpClient.post<unknown>(\n url,\n { userId: options.userId, email: options.email },\n this.mergeHeaders()\n );\n if (!result.ok) return err(result.error);\n return ok(undefined);\n }\n\n async verifyEmailCode(\n userId: string,\n code: string\n ): Promise<Result<{ sessionToken: string }, TryMellonError>> {\n return this.post('/v1/fallback/email/verify', { userId, code }, validateEmailVerifyResponse);\n }\n\n async startOnboarding(\n request: OnboardingStartRequest\n ): Promise<Result<OnboardingStartResponse, TryMellonError>> {\n return this.post('/onboarding/start', request, validateOnboardingStartResponse);\n }\n\n async getOnboardingStatus(\n sessionId: string\n ): Promise<Result<OnboardingStatusResponse, TryMellonError>> {\n return this.get(`/onboarding/${sessionId}/status`, validateOnboardingStatusResponse);\n }\n\n async getOnboardingRegister(\n sessionId: string\n ): Promise<Result<OnboardingRegisterResponseWithChallenge, TryMellonError>> {\n return this.get(`/onboarding/${sessionId}/register`, validateOnboardingRegisterResponse);\n }\n\n async registerOnboardingPasskey(\n sessionId: string,\n request: OnboardingRegisterPasskeyRequest\n ): Promise<Result<OnboardingRegisterPasskeyResponse, TryMellonError>> {\n return this.post(\n `/onboarding/${sessionId}/register-passkey`,\n request,\n validateOnboardingRegisterPasskeyResponse\n );\n }\n\n async completeOnboarding(\n sessionId: string,\n request: OnboardingCompleteRequest\n ): Promise<Result<OnboardingCompleteResponse, TryMellonError>> {\n return this.post(\n `/onboarding/${sessionId}/complete`,\n request,\n validateOnboardingCompleteResponse\n );\n }\n\n async initCrossDeviceAuth(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.post('/v1/auth/cross-device/init', {}, validateCrossDeviceInitResponse);\n }\n\n async initCrossDeviceRegistration(options: {\n externalUserId: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.post(\n '/v1/auth/cross-device/init-registration',\n { external_user_id: options.externalUserId },\n validateCrossDeviceInitResponse\n );\n }\n\n async getCrossDeviceStatus(\n sessionId: string\n ): Promise<Result<CrossDeviceStatusResult, TryMellonError>> {\n return this.get(`/v1/auth/cross-device/status/${sessionId}`, validateCrossDeviceStatusResponse);\n }\n\n /**\n * Fetches WebAuthn options for the cross-device session.\n * Contract: response is CrossDeviceContextResult (auth | registration).\n * Use result.value.type to branch: 'auth' → credentials.get + verify;\n * 'registration' → credentials.create + verify-registration.\n */\n async getCrossDeviceContext(\n sessionId: string\n ): Promise<Result<CrossDeviceContextResult, TryMellonError>> {\n return this.get(\n `/v1/auth/cross-device/context/${sessionId}`,\n validateCrossDeviceContextResponse\n );\n }\n\n async verifyCrossDeviceAuth(\n request: CrossDeviceVerifyRequest\n ): Promise<Result<void, TryMellonError>> {\n const url = `${this.baseUrl}/v1/auth/cross-device/verify`;\n const result = await this.httpClient.post<unknown>(url, request, this.mergeHeaders());\n if (!result.ok) return err(result.error);\n return ok(undefined);\n }\n\n async verifyCrossDeviceRegistration(\n request: CrossDeviceVerifyRegistrationRequest\n ): Promise<Result<void, TryMellonError>> {\n const url = `${this.baseUrl}/v1/auth/cross-device/verify-registration`;\n const result = await this.httpClient.post<unknown>(url, request, this.mergeHeaders());\n if (!result.ok) return err(result.error);\n return ok(undefined);\n }\n\n async verifyAccountRecoveryOtp(\n externalUserId: string,\n otp: string\n ): Promise<Result<RecoveryVerifyResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/verify',\n { external_id: externalUserId, otp },\n validateRecoveryVerifyResponse\n );\n }\n\n async completeAccountRecovery(\n recoverySessionId: string,\n credential: Record<string, unknown>\n ): Promise<Result<RecoveryCompleteResponse, TryMellonError>> {\n return this.post(\n '/v1/users/recovery/complete',\n { recovery_session_id: recoverySessionId, credential },\n validateRecoveryCompleteResponse\n );\n }\n}\n","import type { HttpClient } from './http-client';\nimport type { Logger } from './ports/logger';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { createError, type TryMellonError, type TryMellonErrorCode } from '../errors';\n\nconst RETRY_DELAY_CAP_MS = 30_000;\n\n/**\n * Generates a unique request ID. Uses globalThis.crypto.randomUUID only (Elite: no Node crypto).\n * @throws Error when Web Crypto API is not available (Edge/browser must provide it).\n */\nfunction generateRequestId(): string {\n if (\n typeof globalThis.crypto !== 'undefined' &&\n typeof globalThis.crypto.randomUUID === 'function'\n ) {\n return globalThis.crypto.randomUUID();\n }\n throw new Error('Web Crypto API is required but not available.');\n}\n\n/**\n * Exponential backoff delay for a given attempt (0-based).\n * Cap at RETRY_DELAY_CAP_MS.\n */\nexport function getRetryDelayMs(attempt: number, baseMs: number): number {\n const delay = baseMs * Math.pow(2, attempt);\n return Math.min(delay, RETRY_DELAY_CAP_MS);\n}\n\nfunction shouldRetryOnStatus(method: string, status: number): boolean {\n if (method !== 'GET') return false;\n return status >= 500 || status === 429;\n}\n\nexport class FetchHttpClient implements HttpClient {\n constructor(\n private readonly timeoutMs: number,\n private readonly maxRetries: number = 0,\n private readonly retryDelayMs: number = 1000,\n private readonly logger?: Logger\n ) {}\n\n async get<T>(url: string, headers?: Record<string, string>): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, { method: 'GET', headers });\n }\n\n async post<T>(\n url: string,\n body: unknown,\n headers?: Record<string, string>\n ): Promise<Result<T, TryMellonError>> {\n return this.request<T>(url, {\n method: 'POST',\n body: JSON.stringify(body),\n headers: { 'Content-Type': 'application/json', ...headers },\n });\n }\n\n private async request<T>(url: string, config: RequestInit): Promise<Result<T, TryMellonError>> {\n const method = (config.method ?? 'GET').toUpperCase();\n const requestId = generateRequestId();\n const headers = new Headers(config.headers as HeadersInit);\n headers.set('X-Request-Id', requestId);\n\n if (this.logger) {\n this.logger.debug('request', { requestId, url, method });\n }\n\n let lastError: TryMellonError | Error | unknown;\n\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);\n\n try {\n const response = await fetch(url, {\n ...config,\n headers,\n signal: controller.signal,\n });\n\n if (!response.ok) {\n let errorData: unknown;\n try {\n errorData = await response.json();\n } catch {\n // Ignore JSON parse error\n }\n\n const body = errorData as { message?: string; error?: string } | undefined;\n const message = body?.message ?? response.statusText;\n const rawCode = body?.error;\n const code: TryMellonErrorCode =\n rawCode === 'challenge_mismatch'\n ? 'CHALLENGE_MISMATCH'\n : ((rawCode as TryMellonErrorCode | undefined) ?? 'NETWORK_FAILURE');\n const errResult = createError(code, message, {\n requestId,\n status: response.status,\n statusText: response.statusText,\n data: errorData,\n });\n\n if (shouldRetryOnStatus(method, response.status) && attempt < this.maxRetries) {\n lastError = errResult;\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n continue;\n }\n\n return err(errResult);\n }\n\n if (response.status === 204) {\n return ok(undefined as T);\n }\n const contentLength = response.headers.get('content-length');\n if (contentLength === '0') {\n return ok(undefined as T);\n }\n const data = (await response.json()) as T;\n return ok(data);\n } finally {\n clearTimeout(timeoutId);\n }\n } catch (error) {\n lastError = error;\n const isGet = method === 'GET';\n if (isGet && attempt < this.maxRetries) {\n await new Promise((resolve) =>\n setTimeout(resolve, getRetryDelayMs(attempt, this.retryDelayMs))\n );\n } else {\n break;\n }\n }\n }\n\n if (lastError instanceof Error && lastError.name === 'AbortError') {\n return err(createError('TIMEOUT', 'Request timed out', { requestId }));\n }\n\n return err(\n createError(\n 'NETWORK_FAILURE',\n lastError instanceof Error ? lastError.message : 'Request failed',\n { requestId, cause: lastError }\n )\n );\n }\n}\n","import { createEncodingError } from '../errors';\n\n/**\n * Encodes an ArrayBuffer to base64url using globalThis.btoa (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when btoa is unavailable\n */\nexport function base64UrlEncode(buf: ArrayBuffer): string {\n const bytes = new Uint8Array(buf);\n const binary = Array.from(bytes, (b) => String.fromCharCode(b)).join('');\n\n if (typeof globalThis.btoa === 'undefined') {\n throw createEncodingError('encode');\n }\n const base64 = globalThis.btoa(binary);\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n}\n\n/**\n * Decodes a base64url string to Uint8Array using globalThis.atob (Edge/browser-safe; no Node Buffer).\n * @throws TryMellonError when atob is unavailable\n */\nexport function base64UrlDecode(s: string): Uint8Array {\n if (typeof globalThis.atob === 'undefined') {\n throw createEncodingError('decode');\n }\n\n const base64 = s.replace(/-/g, '+').replace(/_/g, '/');\n const padding = base64.length % 4;\n const padded = padding === 0 ? base64 : base64 + '='.repeat(4 - padding);\n const binary = globalThis.atob(padded);\n\n return Uint8Array.from(binary, (c) => c.charCodeAt(0));\n}\n\n/** Decodes base64url to ArrayBuffer (delegates to base64UrlDecode). */\nexport function base64UrlDecodeToArrayBuffer(s: string): ArrayBuffer {\n const bytes = base64UrlDecode(s);\n const buffer = new ArrayBuffer(bytes.length);\n new Uint8Array(buffer).set(bytes);\n return buffer;\n}\n","import { createError } from '../errors';\nimport { base64UrlEncode } from '../utils/base64url';\nimport type { RegisterFinishRequest, AuthFinishRequest } from '../types';\n\ntype SerializedCredentialForRegister = RegisterFinishRequest['credential'];\ntype SerializedCredentialForAuth = AuthFinishRequest['credential'];\n\n/**\n * Type guard para verificar si una respuesta de credencial es válida.\n */\nfunction isValidCredentialResponse(\n response: unknown\n): response is AuthenticatorAssertionResponse | AuthenticatorAttestationResponse {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'clientDataJSON' in response &&\n response.clientDataJSON instanceof ArrayBuffer\n );\n}\n\n/**\n * Serializa una credencial para registro (finish).\n * Incluye attestationObject requerido para la verificación de registro.\n *\n * @param credential - Credencial WebAuthn obtenida de navigator.credentials.create()\n * @returns Credencial serializada con formato Base64URL\n * @throws {TryMellonError} Si la credencial no tiene la estructura esperada para registro\n */\nexport function serializeCredentialForRegister(\n credential: PublicKeyCredential\n): SerializedCredentialForRegister {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('attestationObject' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for register: attestationObject is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const attestationObject = (response as AuthenticatorAttestationResponse).attestationObject;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n clientDataJSON: base64UrlEncode(clientDataJSON),\n attestationObject: base64UrlEncode(attestationObject),\n },\n type: 'public-key',\n };\n}\n\n/**\n * Serializa una credencial para autenticación (finish).\n * Incluye authenticatorData, signature, y opcionalmente userHandle.\n *\n * @param credential - Credencial WebAuthn obtenida de navigator.credentials.get()\n * @returns Credencial serializada con formato Base64URL\n * @throws {TryMellonError} Si la credencial no tiene la estructura esperada para autenticación\n */\nexport function serializeCredentialForAuth(\n credential: PublicKeyCredential\n): SerializedCredentialForAuth {\n if (!credential.response) {\n throw createError('UNKNOWN_ERROR', 'Credential response is missing', { credential });\n }\n\n const response = credential.response;\n\n if (!isValidCredentialResponse(response)) {\n throw createError('UNKNOWN_ERROR', 'Invalid credential response structure', { response });\n }\n\n if (!('authenticatorData' in response) || !('signature' in response)) {\n throw createError(\n 'UNKNOWN_ERROR',\n 'Invalid credential response structure for auth: authenticatorData or signature is missing',\n { response }\n );\n }\n\n const clientDataJSON = response.clientDataJSON;\n const authenticatorData = (response as AuthenticatorAssertionResponse).authenticatorData;\n const signature = (response as AuthenticatorAssertionResponse).signature;\n const userHandle = (response as AuthenticatorAssertionResponse).userHandle;\n\n return {\n id: credential.id,\n rawId: base64UrlEncode(credential.rawId),\n response: {\n authenticatorData: base64UrlEncode(authenticatorData),\n clientDataJSON: base64UrlEncode(clientDataJSON),\n signature: base64UrlEncode(signature),\n ...(userHandle && { userHandle: base64UrlEncode(userHandle) }),\n },\n type: 'public-key',\n };\n}\n","import type { ClientStatus } from '../types';\n\nexport function isWebAuthnSupported(): boolean {\n try {\n if (typeof navigator === 'undefined' || !navigator.credentials) {\n return false;\n }\n\n if (typeof PublicKeyCredential === 'undefined') {\n return false;\n }\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function isPlatformAuthenticatorAvailable(): Promise<boolean> {\n try {\n if (!isWebAuthnSupported()) {\n return false;\n }\n\n if (typeof PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable !== 'function') {\n return false;\n }\n\n return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n } catch {\n return false;\n }\n}\n\nexport async function getClientStatus(): Promise<ClientStatus> {\n const isPasskeySupported = isWebAuthnSupported();\n const platformAuthenticatorAvailable = await isPlatformAuthenticatorAvailable();\n\n return {\n isPasskeySupported,\n platformAuthenticatorAvailable,\n recommendedFlow: isPasskeySupported ? 'passkey' : 'fallback',\n };\n}\n","import { createCredentialError } from '../errors';\n\nexport function validateCredentialStructure(\n credential: unknown,\n operation: 'create' | 'get' = 'create'\n): asserts credential is PublicKeyCredential {\n if (\n !credential ||\n typeof credential !== 'object' ||\n !('id' in credential) ||\n !('rawId' in credential) ||\n !('response' in credential)\n ) {\n throw createCredentialError(operation);\n }\n}\n","import type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { isWebAuthnSupported } from '../utils/support';\nimport type { EventEmitter } from './events';\nimport type { TryMellonError } from '../errors';\nimport { mapWebAuthnError, createNotSupportedError, createInvalidArgumentError } from '../errors';\nimport { validateCredentialStructure } from '../utils/validation';\n\nexport type CeremonyOperation = 'register' | 'authenticate';\n\nexport interface InvokeCeremonyContext<\n TStartResult,\n TFinishResult,\n TCeremonyOptions extends CredentialCreationOptions | CredentialRequestOptions,\n> {\n operation: CeremonyOperation;\n eventEmitter: EventEmitter;\n start: () => Promise<Result<TStartResult, TryMellonError>>;\n createOptions: (startResult: TStartResult) => Result<TCeremonyOptions, TryMellonError>;\n invoke: (options: TCeremonyOptions) => Promise<Credential | null>;\n finish: (\n startResult: TStartResult,\n credential: PublicKeyCredential\n ) => Promise<Result<TFinishResult, TryMellonError>>;\n}\n\n/**\n * Orquesta un flujo genérico WebAuthn (Ceremonia) para eliminar código duplicado en el SDK.\n * Encapsula la llamada de start, la creación de opciones, la invocación de la API de credenciales\n * del navegador, la validación de la estructura base y la llamada de finish.\n */\nexport async function invokeCeremony<\n TStartResult,\n TFinishResult,\n TCeremonyOptions extends CredentialCreationOptions | CredentialRequestOptions,\n>(\n context: InvokeCeremonyContext<TStartResult, TFinishResult, TCeremonyOptions>\n): Promise<Result<TFinishResult, TryMellonError>> {\n const { operation, eventEmitter, start, createOptions, invoke, finish } = context;\n\n try {\n eventEmitter.emit('start', { type: 'start', operation });\n\n if (!isWebAuthnSupported()) {\n const error = createNotSupportedError();\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 1. Obtener challenge del servidor\n const startResult = await start();\n if (!startResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: startResult.error });\n return err(startResult.error);\n }\n\n // 2. Crear opciones\n const optionsResult = createOptions(startResult.value);\n if (!optionsResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: optionsResult.error });\n return err(optionsResult.error);\n }\n\n // 3. Invocar al navegador\n const credential = (await invoke(optionsResult.value)) as PublicKeyCredential;\n if (!credential) {\n const error = createInvalidArgumentError(\n 'credential',\n `${operation === 'register' ? 'creation' : 'retrieval'} failed`\n );\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n try {\n validateCredentialStructure(credential);\n } catch (e) {\n const error = mapWebAuthnError(e);\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n // 4. Completar en servidor\n const finishResult = await finish(startResult.value, credential);\n if (!finishResult.ok) {\n eventEmitter.emit('error', { type: 'error', error: finishResult.error });\n return err(finishResult.error);\n }\n\n eventEmitter.emit('success', { type: 'success', operation });\n return ok(finishResult.value);\n } catch (error) {\n const tryMellonError = mapWebAuthnError(error);\n eventEmitter.emit('error', { type: 'error', error: tryMellonError });\n return err(tryMellonError);\n }\n}\n","import { createInvalidArgumentError, validateBase64Url, mapWebAuthnError } from '../errors';\nimport { base64UrlDecodeToArrayBuffer } from '../utils/base64url';\nimport type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type {\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n RegisterStartResponse,\n AuthStartResponse,\n} from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\nimport { invokeCeremony } from './ceremony';\n\n/**\n * Crea las opciones de creación de credencial para WebAuthn.\n * Convierte la respuesta del servidor en formato WebAuthn API.\n * WebAuthn protocol: challenge and rp.id are taken from the server only; do not override.\n * Exported for use by OnboardingManager (same-device passkey registration).\n */\nexport function createRegistrationOptions(\n challenge: RegisterStartResponse['challenge'],\n authenticatorType?: 'platform' | 'cross-platform'\n): Result<CredentialCreationOptions, TryMellonError> {\n try {\n validateBase64Url(challenge.challenge, 'challenge');\n validateBase64Url(challenge.user.id, 'user.id');\n\n const challengeBuffer = base64UrlDecodeToArrayBuffer(challenge.challenge);\n const userIdBuffer = base64UrlDecodeToArrayBuffer(challenge.user.id);\n\n // Construir authenticatorSelection: priorizar servidor, permitir override de authenticatorType\n let authenticatorSelection: AuthenticatorSelectionCriteria = {\n userVerification: 'preferred',\n };\n\n if (challenge.authenticatorSelection) {\n // Usar valores del servidor como base\n authenticatorSelection = {\n ...challenge.authenticatorSelection,\n };\n }\n\n // Si el usuario especifica authenticatorType, sobrescribir authenticatorAttachment\n if (authenticatorType) {\n authenticatorSelection = {\n ...authenticatorSelection,\n authenticatorAttachment: authenticatorType,\n };\n }\n\n const publicKey: PublicKeyCredentialCreationOptions = {\n rp: {\n id: challenge.rp.id,\n name: challenge.rp.name,\n },\n user: {\n id: userIdBuffer,\n name: challenge.user.name,\n displayName: challenge.user.displayName,\n },\n challenge: challengeBuffer,\n pubKeyCredParams: challenge.pubKeyCredParams,\n ...(challenge.timeout !== undefined && { timeout: challenge.timeout }),\n attestation: 'none',\n authenticatorSelection,\n ...(challenge.excludeCredentials && {\n excludeCredentials: challenge.excludeCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n };\n\n return ok({ publicKey });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Crea las opciones de autenticación para WebAuthn.\n * Convierte la respuesta del servidor en formato WebAuthn API.\n * WebAuthn protocol: challenge and rpId are taken from the server only; do not override.\n */\nexport function createAuthenticationOptions(\n challenge: AuthStartResponse['challenge'],\n mediation?: AuthenticateOptions['mediation']\n): Result<CredentialRequestOptions, TryMellonError> {\n try {\n validateBase64Url(challenge.challenge, 'challenge');\n const challengeBuffer = base64UrlDecodeToArrayBuffer(challenge.challenge);\n\n return ok({\n publicKey: {\n challenge: challengeBuffer,\n rpId: challenge.rpId,\n ...(challenge.timeout !== undefined && { timeout: challenge.timeout }),\n userVerification: challenge.userVerification ?? 'preferred',\n ...(challenge.allowCredentials && {\n allowCredentials: challenge.allowCredentials.map((cred) => ({\n id: base64UrlDecodeToArrayBuffer(cred.id),\n type: cred.type,\n ...(cred.transports && {\n transports: cred.transports as AuthenticatorTransport[],\n }),\n })),\n }),\n },\n ...(mediation !== undefined && { mediation }),\n });\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n}\n\n/**\n * Registra una nueva passkey para un usuario.\n * Maneja el flujo completo de registro WebAuthn.\n */\nexport async function registerPasskey(\n options: RegisterOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RegisterResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n return invokeCeremony<RegisterStartResponse, RegisterResult, CredentialCreationOptions>({\n operation: 'register',\n eventEmitter,\n start: () => apiClient.startRegister({ external_user_id: extId }),\n createOptions: (startResult) =>\n createRegistrationOptions(startResult.challenge, options.authenticatorType),\n invoke: async (ceremonyOptions) => {\n const opts = { ...ceremonyOptions, ...(options.signal && { signal: options.signal }) };\n return navigator.credentials.create(opts);\n },\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.finishRegister({\n session_id: startResult.session_id,\n credential: serializeCredentialForRegister(credential),\n });\n\n if (!finishResult.ok) return err(finishResult.error);\n\n return ok({\n success: true,\n credentialId: finishResult.value.credential_id,\n credential_id: finishResult.value.credential_id,\n status: finishResult.value.status,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n });\n },\n });\n}\n\n/**\n * Autentica un usuario usando su passkey.\n * Maneja el flujo completo de autenticación WebAuthn.\n */\nexport async function authenticatePasskey(\n options: AuthenticateOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<AuthenticateResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n const hasUserId = extId !== undefined && typeof extId === 'string' && extId.trim() !== '';\n\n return invokeCeremony<AuthStartResponse, AuthenticateResult, CredentialRequestOptions>({\n operation: 'authenticate',\n eventEmitter,\n start: () =>\n apiClient.startAuth(hasUserId ? { external_user_id: (extId as string).trim() } : {}),\n createOptions: (startResult) =>\n createAuthenticationOptions(startResult.challenge, options.mediation),\n invoke: async (ceremonyOptions) => {\n const opts = { ...ceremonyOptions, ...(options.signal && { signal: options.signal }) };\n return navigator.credentials.get(opts);\n },\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.finishAuthentication({\n session_id: startResult.session_id,\n credential: serializeCredentialForAuth(credential),\n });\n\n if (!finishResult.ok) return err(finishResult.error);\n\n return ok({\n authenticated: finishResult.value.authenticated,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n signals: finishResult.value.signals,\n });\n },\n });\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type { OnboardingStartOptions, OnboardingCompleteResult } from '../types';\nimport { createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\nimport type { OnboardingRegisterResponseWithChallenge } from './validators';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class OnboardingManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Executes the full onboarding flow in a single call.\n * 1. Starts onboarding\n * 2. Polls for 'pending_passkey' or 'completed' status\n * 3. If pending_passkey: when API returns challenge, registers passkey (WebAuthn) then completes onboarding\n * 4. If pending_passkey but API does not return challenge: returns NOT_SUPPORTED with onboarding_url for user to complete elsewhere\n */\n async startFlow(\n options: OnboardingStartOptions & { company_name?: string }\n ): Promise<Result<OnboardingCompleteResult, TryMellonError>> {\n const startResult = await this.apiClient.startOnboarding({ user_role: options.user_role });\n if (!startResult.ok) return err(startResult.error);\n\n const { session_id } = startResult.value;\n\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));\n\n const statusResult = await this.apiClient.getOnboardingStatus(session_id);\n if (!statusResult.ok) return err(statusResult.error);\n\n const status = statusResult.value.status;\n const onboarding_url = statusResult.value.onboarding_url;\n\n if (status === 'pending_passkey') {\n const registerInfoResult = await this.apiClient.getOnboardingRegister(session_id);\n if (!registerInfoResult.ok) return err(registerInfoResult.error);\n\n const registerInfo = registerInfoResult.value as OnboardingRegisterResponseWithChallenge;\n\n if (!registerInfo.challenge) {\n return err(\n createError(\n 'NOT_SUPPORTED',\n 'Onboarding requires user action - complete passkey registration at the provided onboarding_url',\n { onboarding_url }\n )\n );\n }\n\n const creationOptionsResult = createRegistrationOptions(registerInfo.challenge);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n const registerPasskeyResult = await this.apiClient.registerOnboardingPasskey(session_id, {\n credential: serializedCredential,\n challenge: registerInfo.challenge.challenge,\n });\n if (!registerPasskeyResult.ok) return err(registerPasskeyResult.error);\n\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n\n if (status === 'completed') {\n const completeResult = await this.apiClient.completeOnboarding(session_id, {\n company_name: options.company_name,\n });\n return completeResult;\n }\n }\n\n return err(createError('TIMEOUT', 'Onboarding timed out'));\n }\n}\n","import type { ApiClient } from './api';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport { createError, mapWebAuthnError } from '../errors';\nimport type { TryMellonError } from '../errors';\nimport type {\n CrossDeviceInitResult,\n CrossDeviceContextAuth,\n CrossDeviceContextRegistration,\n} from '../types';\nimport { createAuthenticationOptions, createRegistrationOptions } from './webauthn';\nimport { serializeCredentialForAuth, serializeCredentialForRegister } from './webauthn-utils';\nimport { validateCredentialStructure } from '../utils/validation';\n\nconst POLL_INTERVAL_MS = 2000;\nconst MAX_POLL_ATTEMPTS = 60; // ~2 minutes\n\nexport class CrossDeviceManager {\n constructor(private readonly apiClient: ApiClient) {}\n\n /**\n * Initializes a cross-device authentication session.\n * Typically called by the desktop side to get a QR code URL.\n */\n async init(): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceAuth();\n }\n\n /**\n * Initializes a cross-device registration session (create account via QR).\n * Typically called by the desktop side to get a QR code URL for new users.\n */\n async initRegistration(options: {\n externalUserId: string;\n }): Promise<Result<CrossDeviceInitResult, TryMellonError>> {\n return this.apiClient.initCrossDeviceRegistration(options);\n }\n\n /**\n * High-level helper to poll for session status until it is completed.\n * Typically called by the desktop side after showing the QR code.\n */\n async waitForSession(\n sessionId: string,\n signal?: AbortSignal\n ): Promise<Result<{ session_token: string; user_id: string }, TryMellonError>> {\n for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt++) {\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n\n const statusResult = await this.apiClient.getCrossDeviceStatus(sessionId);\n if (!statusResult.ok) return err(statusResult.error);\n\n if (statusResult.value.status === 'completed') {\n if (!statusResult.value.session_token || !statusResult.value.user_id) {\n return err(createError('UNKNOWN_ERROR', 'Missing data in completed session'));\n }\n return ok({\n session_token: statusResult.value.session_token,\n user_id: statusResult.value.user_id,\n });\n }\n\n // Wait with abort check\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n await new Promise((resolve) => {\n const timeout = setTimeout(() => {\n resolve(null);\n signal?.removeEventListener('abort', onAbort);\n }, POLL_INTERVAL_MS);\n\n const onAbort = () => {\n clearTimeout(timeout);\n resolve(null);\n };\n signal?.addEventListener('abort', onAbort);\n });\n\n if (signal?.aborted) {\n return err(createError('ABORT_ERROR', 'Operation aborted by user or timeout'));\n }\n }\n\n return err(createError('TIMEOUT', 'Cross-device authentication timed out'));\n }\n\n /**\n * Approves a cross-device session.\n * Typically called by the mobile side after scanning a QR code.\n * Branches by context type: registration → credentials.create + verify-registration;\n * auth → credentials.get + verify.\n */\n async approve(sessionId: string): Promise<Result<void, TryMellonError>> {\n const contextResult = await this.apiClient.getCrossDeviceContext(sessionId);\n if (!contextResult.ok) return err(contextResult.error);\n\n const context = contextResult.value;\n\n if (context.type === 'registration') {\n return this.executeRegistrationApproval(sessionId, context);\n }\n return this.executeAuthApproval(sessionId, context);\n }\n\n /**\n * Executes the registration branch: create credential and verify-registration.\n */\n private async executeRegistrationApproval(\n sessionId: string,\n context: CrossDeviceContextRegistration\n ): Promise<Result<void, TryMellonError>> {\n const creationOptionsResult = createRegistrationOptions(context.options);\n if (!creationOptionsResult.ok) return err(creationOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.create(creationOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'create');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForRegister(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceRegistration({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n\n /**\n * Executes the auth branch: get credential and verify.\n */\n private async executeAuthApproval(\n sessionId: string,\n context: CrossDeviceContextAuth\n ): Promise<Result<void, TryMellonError>> {\n const requestOptionsResult = createAuthenticationOptions(context.options);\n if (!requestOptionsResult.ok) return err(requestOptionsResult.error);\n\n let credential: Credential | null;\n try {\n credential = await navigator.credentials.get(requestOptionsResult.value);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n try {\n validateCredentialStructure(credential, 'get');\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n let serializedCredential;\n try {\n serializedCredential = serializeCredentialForAuth(credential as PublicKeyCredential);\n } catch (e) {\n return err(mapWebAuthnError(e));\n }\n\n return this.apiClient.verifyCrossDeviceAuth({\n session_id: sessionId,\n credential: serializedCredential,\n });\n }\n}\n","import type { EventHandler, EventPayload, TryMellonEvent } from '../types';\n\nexport class EventEmitter {\n private handlers: Map<TryMellonEvent, Set<EventHandler>>;\n\n constructor() {\n this.handlers = new Map();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n let handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n handlersSet = new Set();\n this.handlers.set(event, handlersSet);\n }\n\n handlersSet.add(handler);\n\n return () => {\n this.off(event, handler);\n };\n }\n\n off(event: TryMellonEvent, handler: EventHandler): void {\n const handlersSet = this.handlers.get(event);\n if (!handlersSet) {\n return;\n }\n handlersSet.delete(handler);\n if (handlersSet.size === 0) {\n this.handlers.delete(event);\n }\n }\n\n emit(event: TryMellonEvent, payload: EventPayload): void {\n const handlersSet = this.handlers.get(event);\n if (handlersSet) {\n handlersSet.forEach((handler) => {\n try {\n handler(payload);\n } catch {\n // Silently ignore handler errors to prevent one handler from breaking others\n // Handler errors are the responsibility of the handler implementation\n }\n });\n }\n }\n\n removeAllListeners(): void {\n this.handlers.clear();\n }\n}\n","import type { ApiClient } from './api';\nimport type { EventEmitter } from './events';\nimport type {\n RecoverAccountOptions,\n RecoverAccountResult,\n RecoveryVerifyResponse,\n RegisterStartResponse,\n} from '../types';\nimport type { Result } from '../utils/result';\nimport { ok, err } from '../utils/result';\nimport type { TryMellonError } from '../errors';\nimport { createInvalidArgumentError } from '../errors';\nimport { serializeCredentialForRegister } from './webauthn-utils';\nimport { createRegistrationOptions } from './webauthn';\nimport { invokeCeremony } from './ceremony';\n\n/**\n * Recovers an account using an email OTP and creates a new passkey credential.\n * Manages the complete orchestrated WebAuthn registration flow for recovery.\n */\nexport async function recoverAccount(\n options: RecoverAccountOptions,\n apiClient: ApiClient,\n eventEmitter: EventEmitter\n): Promise<Result<RecoverAccountResult, TryMellonError>> {\n const extId = options.externalUserId ?? options.external_user_id;\n if (!extId || typeof extId !== 'string' || extId.trim() === '') {\n const error = createInvalidArgumentError('externalUserId', 'must be a non-empty string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n if (!options.otp || typeof options.otp !== 'string' || options.otp.trim().length !== 6) {\n const error = createInvalidArgumentError('otp', 'must be a 6-digit string');\n eventEmitter.emit('error', { type: 'error', error });\n return err(error);\n }\n\n return invokeCeremony<RecoveryVerifyResponse, RecoverAccountResult, CredentialCreationOptions>({\n operation: 'register',\n eventEmitter,\n start: () => apiClient.verifyAccountRecoveryOtp(extId, options.otp),\n createOptions: (startResult) =>\n createRegistrationOptions(startResult.challenge as RegisterStartResponse['challenge']),\n invoke: async (ceremonyOptions) => navigator.credentials.create(ceremonyOptions),\n finish: async (startResult, credential) => {\n const finishResult = await apiClient.completeAccountRecovery(\n startResult.recovery_session_id,\n serializeCredentialForRegister(credential)\n );\n\n if (!finishResult.ok) return err(finishResult.error);\n\n return ok({\n success: true,\n credentialId: finishResult.value.credential_id,\n status: finishResult.value.status,\n sessionToken: finishResult.value.session_token,\n user: {\n userId: finishResult.value.user.user_id,\n externalUserId: finishResult.value.user.external_user_id,\n email: finishResult.value.user.email,\n metadata: finishResult.value.user.metadata,\n },\n });\n },\n });\n}\n","export const COSE_ALGORITHM_ES256 = -7;\nexport const COSE_ALGORITHM_RS256 = -257;\n\nexport const DEFAULT_API_BASE_URL = 'https://api.trymellonauth.com';\nexport const DEFAULT_TELEMETRY_ENDPOINT = 'https://api.trymellonauth.com/v1/telemetry';\nexport const DEFAULT_TIMEOUT_MS = 30000;\nexport const DEFAULT_MAX_RETRIES = 3;\nexport const DEFAULT_RETRY_DELAY_MS = 1000;\n\nexport const MIN_TIMEOUT_MS = 1000;\nexport const MAX_TIMEOUT_MS = 300000;\nexport const MIN_MAX_RETRIES = 0;\nexport const MAX_MAX_RETRIES = 10;\nexport const MIN_RETRY_DELAY_MS = 100;\nexport const MAX_RETRY_DELAY_MS = 10000;\n\n/**\n * Fixed session token returned by register() and authenticate() when sandbox mode is enabled.\n * Backends MUST NOT accept this token in production; only in development for testing the integration flow.\n */\nexport const SANDBOX_SESSION_TOKEN = 'trymellon_sandbox_session_token_v1';\n","import type { TelemetrySender, TelemetryPayload } from '../ports/telemetry';\n\n/**\n * Default telemetry sender: sends payload via sendBeacon (or fetch) to the given endpoint.\n * No retries; fire-and-forget.\n */\nexport function createDefaultTelemetrySender(endpoint: string): TelemetrySender {\n return {\n async send(payload: TelemetryPayload): Promise<void> {\n const body = JSON.stringify(payload);\n if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {\n navigator.sendBeacon(endpoint, body);\n return;\n }\n if (typeof fetch !== 'undefined') {\n await fetch(endpoint, {\n method: 'POST',\n body,\n headers: { 'Content-Type': 'application/json' },\n keepalive: true,\n });\n }\n },\n };\n}\n","export type TelemetryEvent = 'register' | 'authenticate';\n\nexport type TelemetryPayload = {\n event: TelemetryEvent;\n latencyMs: number;\n ok: true;\n};\n\nexport interface TelemetrySender {\n send(payload: TelemetryPayload): Promise<void>;\n}\n\n/**\n * Builds the minimal telemetry payload (no PII).\n */\nexport function buildTelemetryPayload(event: TelemetryEvent, latencyMs: number): TelemetryPayload {\n return { event, latencyMs, ok: true };\n}\n","import { ApiClient } from './api';\nimport { FetchHttpClient } from './fetch-client';\nimport { OnboardingManager } from './onboarding-manager';\nimport { CrossDeviceManager } from './cross-device-manager';\nimport { EventEmitter } from './events';\nimport { registerPasskey, authenticatePasskey } from './webauthn';\nimport { recoverAccount } from './recover';\nimport { isWebAuthnSupported, getClientStatus } from '../utils/support';\nimport { validateUrl, validateRange, createInvalidArgumentError } from '../errors';\nimport {\n DEFAULT_API_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n DEFAULT_MAX_RETRIES,\n DEFAULT_RETRY_DELAY_MS,\n DEFAULT_TELEMETRY_ENDPOINT,\n MIN_TIMEOUT_MS,\n MAX_TIMEOUT_MS,\n MIN_MAX_RETRIES,\n MAX_MAX_RETRIES,\n MIN_RETRY_DELAY_MS,\n MAX_RETRY_DELAY_MS,\n SANDBOX_SESSION_TOKEN,\n} from './constants';\nimport { createDefaultTelemetrySender } from './adapters/telemetry-sender';\nimport { buildTelemetryPayload, type TelemetrySender } from './ports/telemetry';\nimport type {\n TryMellonConfig,\n RegisterOptions,\n RegisterResult,\n AuthenticateOptions,\n AuthenticateResult,\n ClientStatus,\n TryMellonEvent,\n EventHandler,\n EmailFallbackStartOptions,\n EmailFallbackVerifyOptions,\n EmailFallbackVerifyResult,\n SessionValidateResponse,\n RecoverAccountOptions,\n} from '../types';\nimport { ok, err, type Result } from '../utils/result';\nimport { type TryMellonError, isTryMellonError } from '../errors';\n\ndeclare const __VERSION__: string;\n\nexport class TryMellon {\n private readonly sandbox: boolean;\n private readonly sandboxToken: string;\n private apiClient: ApiClient;\n private eventEmitter: EventEmitter;\n private telemetrySender: TelemetrySender | undefined;\n private crossDeviceManager: CrossDeviceManager;\n public onboarding: OnboardingManager;\n\n /**\n * Configura una nueva instancia de TryMellon.\n * Valida la configuración y retorna un Result.\n * @param config Configuración del SDK\n */\n static create(config: TryMellonConfig): Result<TryMellon, TryMellonError> {\n try {\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n return err(createInvalidArgumentError('appId', 'must be a non-empty string'));\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n return err(createInvalidArgumentError('publishableKey', 'must be a non-empty string'));\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n // Safe to instantiate now\n return ok(new TryMellon(config));\n } catch (e) {\n if (isTryMellonError(e)) {\n return err(e);\n }\n return err(createInvalidArgumentError('config', (e as Error).message));\n }\n }\n\n /**\n * @deprecated Use `TryMellon.create(config)` instead to handle validation errors safely.\n * This constructor will throw errors if configuration is invalid.\n */\n constructor(config: TryMellonConfig) {\n this.sandbox = config.sandbox === true;\n this.sandboxToken =\n this.sandbox && config.sandboxToken != null && config.sandboxToken !== ''\n ? config.sandboxToken\n : SANDBOX_SESSION_TOKEN;\n\n const appId = config.appId;\n const publishableKey = config.publishableKey;\n\n // Legacy validation for direct constructor usage (still throws to maintain behavior for legacy code,\n // but create() handles this safely before calling constructor)\n if (!appId || typeof appId !== 'string' || appId.trim() === '') {\n throw createInvalidArgumentError('appId', 'must be a non-empty string');\n }\n if (!publishableKey || typeof publishableKey !== 'string' || publishableKey.trim() === '') {\n throw createInvalidArgumentError('publishableKey', 'must be a non-empty string');\n }\n\n const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;\n // validateUrl throws, which is expected for the constructor. create() catches it.\n validateUrl(apiBaseUrl, 'apiBaseUrl');\n\n const timeoutMs = config.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n validateRange(timeoutMs, 'timeoutMs', MIN_TIMEOUT_MS, MAX_TIMEOUT_MS);\n\n if (config.maxRetries !== undefined) {\n validateRange(config.maxRetries, 'maxRetries', MIN_MAX_RETRIES, MAX_MAX_RETRIES);\n }\n\n if (config.retryDelayMs !== undefined) {\n validateRange(config.retryDelayMs, 'retryDelayMs', MIN_RETRY_DELAY_MS, MAX_RETRY_DELAY_MS);\n }\n\n const maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;\n const retryDelayMs = config.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n const httpClient = new FetchHttpClient(timeoutMs, maxRetries, retryDelayMs, config.logger);\n\n const originHeader =\n config.origin ??\n (typeof window !== 'undefined' && window?.location?.origin\n ? window.location.origin\n : undefined);\n\n const defaultHeaders: Record<string, string> = {\n 'X-App-Id': appId.trim(),\n Authorization: `Bearer ${publishableKey.trim()}`,\n ...(originHeader && { Origin: originHeader }),\n };\n\n this.apiClient = new ApiClient(httpClient, apiBaseUrl, defaultHeaders);\n this.onboarding = new OnboardingManager(this.apiClient);\n this.crossDeviceManager = new CrossDeviceManager(this.apiClient);\n this.eventEmitter = new EventEmitter();\n\n if (config.enableTelemetry) {\n this.telemetrySender =\n config.telemetrySender ??\n createDefaultTelemetrySender(config.telemetryEndpoint ?? DEFAULT_TELEMETRY_ENDPOINT);\n }\n }\n\n static isSupported(): boolean {\n return isWebAuthnSupported();\n }\n\n async register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>> {\n if (this.sandbox) {\n const externalUserId =\n options.externalUserId ??\n (options as { external_user_id?: string }).external_user_id ??\n 'sandbox';\n return Promise.resolve(\n ok({\n success: true,\n credentialId: '',\n status: 'sandbox',\n sessionToken: this.sandboxToken,\n user: {\n userId: 'sandbox-user',\n externalUserId: typeof externalUserId === 'string' ? externalUserId : 'sandbox',\n },\n })\n );\n }\n const start = Date.now();\n const result = await registerPasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('register', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n\n async authenticate(\n options: AuthenticateOptions\n ): Promise<Result<AuthenticateResult, TryMellonError>> {\n if (this.sandbox) {\n const externalUserId =\n options.externalUserId ??\n (options as { external_user_id?: string }).external_user_id ??\n 'sandbox';\n return Promise.resolve(\n ok({\n authenticated: true,\n sessionToken: this.sandboxToken,\n user: {\n userId: 'sandbox-user',\n externalUserId: typeof externalUserId === 'string' ? externalUserId : 'sandbox',\n },\n })\n );\n }\n const start = Date.now();\n const result = await authenticatePasskey(options, this.apiClient, this.eventEmitter);\n if (result.ok && this.telemetrySender) {\n this.telemetrySender\n .send(buildTelemetryPayload('authenticate', Date.now() - start))\n .catch(() => {});\n }\n return result;\n }\n\n async validateSession(\n sessionToken: string\n ): Promise<Result<SessionValidateResponse, TryMellonError>> {\n if (this.sandbox && sessionToken === this.sandboxToken) {\n return Promise.resolve(\n ok({\n valid: true,\n user_id: 'sandbox-user',\n external_user_id: 'sandbox',\n tenant_id: 'sandbox-tenant',\n app_id: 'sandbox-app',\n })\n );\n }\n return this.apiClient.validateSession(sessionToken);\n }\n\n async getStatus(): Promise<ClientStatus> {\n return getClientStatus();\n }\n\n on(event: TryMellonEvent, handler: EventHandler): () => void {\n return this.eventEmitter.on(event, handler);\n }\n\n version(): string {\n return typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.0.0';\n }\n\n fallback = {\n email: {\n start: async (options: EmailFallbackStartOptions): Promise<Result<void, TryMellonError>> => {\n return this.apiClient.startEmailFallback(options);\n },\n verify: async (\n options: EmailFallbackVerifyOptions\n ): Promise<Result<EmailFallbackVerifyResult, TryMellonError>> => {\n return this.apiClient.verifyEmailCode(options.userId, options.code);\n },\n },\n };\n\n auth = {\n crossDevice: {\n init: () => this.crossDeviceManager.init(),\n initRegistration: (options: { externalUserId: string }) =>\n this.crossDeviceManager.initRegistration(options),\n waitForSession: (sessionId: string, signal?: AbortSignal) =>\n this.crossDeviceManager.waitForSession(sessionId, signal),\n approve: (sessionId: string) => this.crossDeviceManager.approve(sessionId),\n },\n recoverAccount: async (options: RecoverAccountOptions) => {\n return recoverAccount(options, this.apiClient, this.eventEmitter);\n },\n };\n}\n"],"mappings":"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","names":["angular_exports","__export","TRYMELLON_CONFIG","TryMellonService","provideTryMellonConfig","__toCommonJS","import_core","ok","value","err","error","TryMellonError","_TryMellonError","code","message","details","DEFAULT_MESSAGES","createError","isTryMellonError","error","createNotSupportedError","createInvalidArgumentError","field","reason","createError","createCredentialError","operation","createEncodingError","type","validateUrl","url","fieldName","urlObj","createInvalidArgumentError","error","isTryMellonError","validateRange","value","min","max","validateBase64Url","s","DOM_EXCEPTION_ERROR_MAP","mapWebAuthnError","name","message","errorCode","createError","isObject","value","isString","isNumber","isBoolean","isArray","validationError","message","details","err","createError","required","obj","key","validateChallengeRP","rp","data","isObject","isString","validationError","ok","validateChallengeUser","user","validatePubKeyCredParams","params","isArray","item","isNumber","validateUserEntity","userId","required","externalUserId","email","metadata","validateRegisterStartResponse","data","isObject","validationError","session_id","required","isString","challenge","rpResult","validateChallengeRP","userResult","validateChallengeUser","challengeStr","pubKeyCredParamsResult","validatePubKeyCredParams","timeout","isNumber","excludeCredentials","isArray","c","authenticatorSelection","ok","validateAuthStartResponse","ch","rpId","allowCredentials","userVerification","validateRegisterFinishResponse","credential_id","status","session_token","user","validateUserEntity","validateAuthFinishResponse","authenticated","signals","isBoolean","validateSessionValidateResponse","data","isObject","validationError","valid","required","user_id","external_user_id","tenant_id","app_id","isBoolean","isString","ok","validateEmailVerifyResponse","data","isObject","validationError","sessionToken","required","isString","ok","ONBOARDING_STATUSES","REGISTER_PASSKEY_STATUSES","validateOnboardingStartResponse","data","isObject","validationError","session_id","required","onboarding_url","expires_in","isString","isNumber","ok","validateOnboardingStatusResponse","status","validateOnboardingRegisterResponse","challenge","parsedChallenge","chResult","validateOnboardingChallenge","rp","user","challengeStr","pubKeyCredParams","isArray","item","validateOnboardingRegisterPasskeyResponse","user_id","tenant_id","validateOnboardingCompleteResponse","session_token","isCreationOptionsShape","opts","o","isRequestOptionsShape","validateCrossDeviceInitResponse","data","isObject","validationError","session_id","qr_url","expires_at","isString","ok","validateCrossDeviceStatusResponse","status","validateCrossDeviceContextResponse","rawType","type","options","validateRecoveryVerifyResponse","data","isObject","validationError","challenge","required","recovery_session_id","isString","ok","validateRecoveryCompleteResponse","status","session_token","user","credential_id","user_id","userObj","ApiClient","httpClient","baseUrl","defaultHeaders","extra","path","body","validate","url","result","err","headers","request","validateRegisterStartResponse","validateAuthStartResponse","validateRegisterFinishResponse","validateAuthFinishResponse","sessionToken","validateSessionValidateResponse","options","ok","userId","code","validateEmailVerifyResponse","validateOnboardingStartResponse","sessionId","validateOnboardingStatusResponse","validateOnboardingRegisterResponse","validateOnboardingRegisterPasskeyResponse","validateOnboardingCompleteResponse","validateCrossDeviceInitResponse","validateCrossDeviceStatusResponse","validateCrossDeviceContextResponse","externalUserId","otp","validateRecoveryVerifyResponse","recoverySessionId","credential","validateRecoveryCompleteResponse","RETRY_DELAY_CAP_MS","generateRequestId","getRetryDelayMs","attempt","baseMs","delay","shouldRetryOnStatus","method","status","FetchHttpClient","timeoutMs","maxRetries","retryDelayMs","logger","url","headers","body","config","requestId","lastError","controller","timeoutId","response","errorData","message","rawCode","errResult","createError","resolve","err","ok","data","error","base64UrlEncode","buf","bytes","binary","b","createEncodingError","base64UrlDecode","s","base64","padding","padded","c","base64UrlDecodeToArrayBuffer","buffer","isValidCredentialResponse","response","serializeCredentialForRegister","credential","createError","clientDataJSON","attestationObject","base64UrlEncode","serializeCredentialForAuth","authenticatorData","signature","userHandle","isWebAuthnSupported","isPlatformAuthenticatorAvailable","getClientStatus","isPasskeySupported","platformAuthenticatorAvailable","validateCredentialStructure","credential","operation","createCredentialError","invokeCeremony","context","operation","eventEmitter","start","createOptions","invoke","finish","isWebAuthnSupported","error","createNotSupportedError","err","startResult","optionsResult","credential","createInvalidArgumentError","validateCredentialStructure","e","mapWebAuthnError","finishResult","ok","tryMellonError","createRegistrationOptions","challenge","authenticatorType","validateBase64Url","challengeBuffer","base64UrlDecodeToArrayBuffer","userIdBuffer","authenticatorSelection","publicKey","cred","ok","e","err","mapWebAuthnError","createAuthenticationOptions","mediation","registerPasskey","options","apiClient","eventEmitter","extId","error","createInvalidArgumentError","invokeCeremony","startResult","ceremonyOptions","opts","credential","finishResult","serializeCredentialForRegister","authenticatePasskey","hasUserId","serializeCredentialForAuth","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","OnboardingManager","apiClient","options","startResult","err","session_id","attempt","resolve","statusResult","status","onboarding_url","registerInfoResult","registerInfo","createError","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","registerPasskeyResult","POLL_INTERVAL_MS","MAX_POLL_ATTEMPTS","CrossDeviceManager","apiClient","options","sessionId","signal","attempt","err","createError","statusResult","ok","resolve","timeout","onAbort","contextResult","context","creationOptionsResult","createRegistrationOptions","credential","e","mapWebAuthnError","validateCredentialStructure","serializedCredential","serializeCredentialForRegister","requestOptionsResult","createAuthenticationOptions","serializeCredentialForAuth","EventEmitter","event","handler","handlersSet","payload","recoverAccount","options","apiClient","eventEmitter","extId","error","createInvalidArgumentError","err","invokeCeremony","startResult","createRegistrationOptions","ceremonyOptions","credential","finishResult","serializeCredentialForRegister","ok","DEFAULT_API_BASE_URL","DEFAULT_TELEMETRY_ENDPOINT","SANDBOX_SESSION_TOKEN","createDefaultTelemetrySender","endpoint","payload","body","buildTelemetryPayload","event","latencyMs","TryMellon","_TryMellon","config","appId","publishableKey","err","createInvalidArgumentError","apiBaseUrl","DEFAULT_API_BASE_URL","validateUrl","timeoutMs","validateRange","ok","e","isTryMellonError","SANDBOX_SESSION_TOKEN","maxRetries","retryDelayMs","httpClient","FetchHttpClient","originHeader","defaultHeaders","ApiClient","OnboardingManager","CrossDeviceManager","EventEmitter","createDefaultTelemetrySender","DEFAULT_TELEMETRY_ENDPOINT","isWebAuthnSupported","options","externalUserId","start","result","registerPasskey","buildTelemetryPayload","authenticatePasskey","sessionToken","getClientStatus","event","handler","sessionId","signal","recoverAccount","TRYMELLON_CONFIG","_TryMellonService_decorators","_init","TryMellonService","TryMellon","__decoratorStart","__decorateElement","__runInitializers","provideTryMellonConfig","config","TRYMELLON_CONFIG"]}