@trymellon/js 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- type TryMellonErrorCode = 'NOT_SUPPORTED' | 'USER_CANCELLED' | 'PASSKEY_NOT_FOUND' | 'SESSION_EXPIRED' | 'NETWORK_FAILURE' | 'INVALID_ARGUMENT' | 'TIMEOUT' | 'ABORTED' | 'ABORT_ERROR' | 'CHALLENGE_MISMATCH' | 'UNKNOWN_ERROR';
1
+ type TryMellonErrorCode = 'NOT_SUPPORTED' | 'USER_CANCELLED' | 'PASSKEY_NOT_FOUND' | 'SESSION_EXPIRED' | 'NETWORK_FAILURE' | 'INVALID_ARGUMENT' | 'TIMEOUT' | 'ABORTED' | 'ABORT_ERROR' | 'CHALLENGE_MISMATCH' | 'TICKET_NOT_FOUND' | 'TICKET_EXPIRED' | 'TICKET_ALREADY_USED' | 'PIN_MISMATCH' | 'PIN_LOCKED' | 'BRIDGE_SESSION_EXPIRED' | 'UNKNOWN_ERROR';
2
2
  declare class TryMellonError extends Error {
3
3
  readonly code: TryMellonErrorCode;
4
4
  readonly details?: unknown;
@@ -37,6 +37,8 @@ type Branded<T, B> = T & {
37
37
  };
38
38
  type AppId = Branded<string, 'AppId'>;
39
39
  type ExternalUserId = Branded<string, 'ExternalUserId'>;
40
+ /** 64-character hex string (SHA-256). Used to bind enrollment ticket to browser context. */
41
+ type ContextHash = Branded<string, 'ContextHash'>;
40
42
  type TryMellonConfig = {
41
43
  /** Application identifier (tenant). Required for API requests. */
42
44
  appId: string | AppId;
@@ -70,6 +72,14 @@ type TryMellonConfig = {
70
72
  * Set this in Node or when the document origin is not the correct one (e.g. SSR).
71
73
  */
72
74
  origin?: string;
75
+ /**
76
+ * Optional storage for context hash (e.g. sessionStorage). If not set, browser sessionStorage or in-memory fallback is used.
77
+ * Injected for testability and SSR; must implement getItem/setItem.
78
+ */
79
+ contextHashStorage?: {
80
+ getItem(key: string): string | null;
81
+ setItem(key: string, value: string): void;
82
+ };
73
83
  };
74
84
  interface RegisterOptions {
75
85
  /**
@@ -117,19 +127,19 @@ type SuccessEventUserInfo = {
117
127
  /** Success payload: token always present (03-eventos-seguridad). Nonce when flow generates it. */
118
128
  type SuccessEventPayload = {
119
129
  type: 'success';
120
- operation: 'register' | 'authenticate';
130
+ operation: 'register' | 'authenticate' | 'enroll';
121
131
  token: string;
122
132
  user?: SuccessEventUserInfo;
123
133
  nonce?: string;
124
134
  };
125
135
  type EventPayload = {
126
136
  type: 'start';
127
- operation: 'register' | 'authenticate';
137
+ operation: 'register' | 'authenticate' | 'enroll';
128
138
  nonce?: string;
129
139
  } | SuccessEventPayload | {
130
140
  type: 'error';
131
141
  error: TryMellonError;
132
- operation?: 'register' | 'authenticate';
142
+ operation?: 'register' | 'authenticate' | 'enroll';
133
143
  nonce?: string;
134
144
  } | {
135
145
  type: 'cancelled';
@@ -152,6 +162,31 @@ type EmailFallbackVerifyResult = {
152
162
  /** Set when successUrl was passed and allowed by application allowlist */
153
163
  redirectUrl?: string;
154
164
  };
165
+ type EnrollOptions = {
166
+ ticketId: string;
167
+ signal?: AbortSignal;
168
+ };
169
+ /** Result of finish enrollment; aligns with backend envelope (session_token). */
170
+ type EnrollmentResult = {
171
+ sessionToken: string;
172
+ };
173
+ /** Backend response for POST /v1/enrollment/register/options. Validators use this shape. */
174
+ type EnrollmentStartResponse = {
175
+ session_id: string;
176
+ challenge: RegisterStartResponse['challenge'];
177
+ };
178
+ /** Backend response for POST /v1/enrollment/register. Validators use this shape. */
179
+ type EnrollmentFinishResponse = {
180
+ credential_id: string;
181
+ status: string;
182
+ session_token: string;
183
+ user: {
184
+ user_id: string;
185
+ external_user_id?: string;
186
+ email?: string;
187
+ metadata?: Record<string, unknown>;
188
+ };
189
+ };
155
190
  type RecoveryVerifyResponse = {
156
191
  challenge: Record<string, unknown>;
157
192
  recovery_session_id: string;
@@ -288,6 +323,62 @@ type CrossDeviceVerifyRegistrationRequest = {
288
323
  session_id: string;
289
324
  credential: RegisterFinishRequest['credential'];
290
325
  };
326
+ /** Response from GET context/:sessionId (auth or registration). Aligns with backend unwrapped result. */
327
+ type BridgeContextResponse = {
328
+ type: 'auth' | 'registration';
329
+ options: Record<string, unknown>;
330
+ application_name?: string;
331
+ };
332
+ /** Response from POST verify/:sessionId (challenge / options for WebAuthn). */
333
+ type BridgeChallengeResponse = {
334
+ session_id: string;
335
+ challenge?: string;
336
+ registration_options?: Record<string, unknown>;
337
+ authentication_options?: Record<string, unknown>;
338
+ };
339
+ /** Backend result of POST complete (enrollment). Validators use this shape. */
340
+ type BridgeCompleteEnrollmentResult = {
341
+ credential_id: string;
342
+ entity_id: string;
343
+ user_id: string;
344
+ session_token: string;
345
+ };
346
+ /** Backend result of POST complete (auth). */
347
+ type BridgeCompleteAuthResult = {
348
+ session_token: string;
349
+ };
350
+ /** Options for bridge flows: PIN callback, optional preset PIN, abort signal. */
351
+ type BridgeOptions = {
352
+ onPinRequired?: () => Promise<string>;
353
+ presencePin?: string;
354
+ signal?: AbortSignal;
355
+ };
356
+ /** Public result of bridge enrollment: sessionToken and optional credential/user/entity ids. */
357
+ type BridgeEnrollmentResult = {
358
+ sessionToken: string;
359
+ credentialId?: string;
360
+ userId?: string;
361
+ entityId?: string;
362
+ };
363
+ /** Public result of bridge auth: sessionToken only. */
364
+ type BridgeAuthResult = {
365
+ sessionToken: string;
366
+ };
367
+ /** Union: bridge completion returns enrollment or auth result. */
368
+ type BridgeResult = BridgeEnrollmentResult | BridgeAuthResult;
369
+ /** Status snapshot from GET .../status/:sessionId (polling or SSE event). Terminal: pin_verified | pin_locked | completed. */
370
+ type BridgeStatusSnapshot = {
371
+ status: 'pending' | 'pin_verified' | 'pin_locked' | 'completed';
372
+ ts?: string;
373
+ };
374
+ /** Options for complete(): BridgeOptions plus kind and enrollment-only fields. */
375
+ type BridgeCompleteOptions = BridgeOptions & {
376
+ kind: 'enrollment' | 'auth';
377
+ /** Required when completing enrollment bridge. */
378
+ ticketId?: string;
379
+ /** Required when completing enrollment bridge. */
380
+ entityId?: string;
381
+ };
291
382
  type RegisterStartRequest = {
292
383
  external_user_id: string;
293
384
  };
@@ -508,6 +599,8 @@ type OnboardingRegisterResponseWithChallenge = OnboardingRegisterResponse & {
508
599
  challenge?: RegisterStartResponse['challenge'];
509
600
  };
510
601
 
602
+ /** Bridge kind: enrollment-bridge (registration flow) or auth-bridge (auth flow). */
603
+ type BridgeKind = 'enrollment' | 'auth';
511
604
  declare class ApiClient {
512
605
  private readonly httpClient;
513
606
  private readonly baseUrl;
@@ -554,6 +647,49 @@ declare class ApiClient {
554
647
  verifyCrossDeviceRegistration(request: CrossDeviceVerifyRegistrationRequest): Promise<Result<void, TryMellonError>>;
555
648
  verifyAccountRecoveryOtp(externalUserId: string, otp: string): Promise<Result<RecoveryVerifyResponse, TryMellonError>>;
556
649
  completeAccountRecovery(recoverySessionId: string, credential: Record<string, unknown>): Promise<Result<RecoveryCompleteResponse, TryMellonError>>;
650
+ startEnrollment(ticketId: string, contextHash: string, headers?: Record<string, string>): Promise<Result<EnrollmentStartResponse, TryMellonError>>;
651
+ finishEnrollment(ticketId: string, body: {
652
+ credential: unknown;
653
+ context_hash: string;
654
+ }, headers?: Record<string, string>): Promise<Result<EnrollmentFinishResponse, TryMellonError>>;
655
+ private bridgePrefix;
656
+ getBridgeContext(sessionId: string, kind: BridgeKind, headers?: Record<string, string>): Promise<Result<BridgeContextResponse, TryMellonError>>;
657
+ verifyBridgePin(sessionId: string, pin: string, kind: BridgeKind, headers?: Record<string, string>): Promise<Result<BridgeChallengeResponse, TryMellonError>>;
658
+ completeBridgeEnrollment(body: {
659
+ session_id: string;
660
+ ticket_id: string;
661
+ entity_id: string;
662
+ context_hash: string;
663
+ registration_response: {
664
+ id: string;
665
+ rawId: string;
666
+ response: {
667
+ clientDataJSON: string;
668
+ attestationObject: string;
669
+ };
670
+ type: string;
671
+ };
672
+ }, headers?: Record<string, string>): Promise<Result<BridgeCompleteEnrollmentResult, TryMellonError>>;
673
+ completeBridgeAuth(body: {
674
+ session_id: string;
675
+ credential: {
676
+ id: string;
677
+ rawId: string;
678
+ response: {
679
+ authenticatorData: string;
680
+ clientDataJSON: string;
681
+ signature: string;
682
+ userHandle?: string;
683
+ };
684
+ type: string;
685
+ };
686
+ }, headers?: Record<string, string>): Promise<Result<BridgeCompleteAuthResult, TryMellonError>>;
687
+ /**
688
+ * Full URL for GET bridge status (polling or EventSource). Same path as getBridgeStatus.
689
+ * Used by BridgeManager for SSE when EventSource is available (browser only; Node has no EventSource).
690
+ */
691
+ getBridgeStatusUrl(sessionId: string, kind: BridgeKind): string;
692
+ getBridgeStatus(sessionId: string, kind: BridgeKind, headers?: Record<string, string>): Promise<Result<BridgeStatusSnapshot, TryMellonError>>;
557
693
  }
558
694
 
559
695
  declare class OnboardingManager {
@@ -581,6 +717,9 @@ declare class TryMellon {
581
717
  private authService;
582
718
  private recoveryService;
583
719
  onboarding: OnboardingManager;
720
+ private readonly enrollmentManager;
721
+ private readonly bridgeManager;
722
+ private readonly contextHashStorage;
584
723
  /**
585
724
  * Creates a new TryMellon instance.
586
725
  * Validates config and returns a Result.
@@ -592,9 +731,25 @@ declare class TryMellon {
592
731
  * This constructor will throw errors if configuration is invalid.
593
732
  */
594
733
  constructor(config: TryMellonConfig);
734
+ /**
735
+ * Bridge (KP-BRIDGE-04): complete enrollment or auth from a second device (e.g. mobile scanning desktop QR).
736
+ * Use kind 'enrollment' for enrollment-bridge sessions, 'auth' for auth-bridge sessions.
737
+ */
738
+ get bridge(): {
739
+ getContext(sessionId: string, kind: 'enrollment' | 'auth'): Promise<Result<BridgeContextResponse, TryMellonError>>;
740
+ verifyPin(sessionId: string, pin: string, kind: 'enrollment' | 'auth'): Promise<Result<BridgeChallengeResponse, TryMellonError>>;
741
+ complete(sessionId: string, options?: BridgeCompleteOptions): Promise<Result<BridgeResult, TryMellonError>>;
742
+ waitForResult(sessionId: string, options?: {
743
+ useSse?: boolean;
744
+ kind?: 'enrollment' | 'auth';
745
+ timeoutMs?: number;
746
+ }): Promise<Result<BridgeStatusSnapshot, TryMellonError>>;
747
+ };
595
748
  static isSupported(): boolean;
596
749
  register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>>;
597
750
  authenticate(options: AuthenticateOptions): Promise<Result<AuthenticateResult, TryMellonError>>;
751
+ enroll(options: EnrollOptions): Promise<Result<EnrollmentResult, TryMellonError>>;
752
+ getContextHash(): string;
598
753
  validateSession(sessionToken: string): Promise<Result<SessionValidateResponse, TryMellonError>>;
599
754
  getStatus(): Promise<ClientStatus>;
600
755
  on(event: TryMellonEvent, handler: EventHandler): () => void;
@@ -636,4 +791,4 @@ declare class ConsoleLogger implements Logger {
636
791
  error(message: string, meta?: Record<string, unknown>): void;
637
792
  }
638
793
 
639
- export { type AuthenticateOptions, type AuthenticateResult, type ClientStatus, ConsoleLogger, type EmailFallbackStartOptions, type EmailFallbackVerifyOptions, type EmailFallbackVerifyResult, type EventHandler, type EventPayload, type LogLevel, type Logger, type OnboardingCompleteOptions, type OnboardingCompleteResult, type OnboardingRegisterPasskeyOptions, type OnboardingRegisterPasskeyResult, type OnboardingRegisterResult, type OnboardingStartOptions, type OnboardingStartResult, type OnboardingStatusResult, type RegisterOptions, type RegisterResult, type Result, SANDBOX_SESSION_TOKEN, type SessionValidateResponse, TryMellon, type TryMellonConfig, TryMellonError, type TryMellonErrorCode, type TryMellonEvent, createError, createInvalidArgumentError, createNetworkError, createNotSupportedError, createTimeoutError, createUserCancelledError, err, isTryMellonError, mapWebAuthnError, ok };
794
+ export { type AuthenticateOptions, type AuthenticateResult, type BridgeAuthResult, type BridgeChallengeResponse, type BridgeCompleteOptions, type BridgeContextResponse, type BridgeEnrollmentResult, type BridgeOptions, type BridgeResult, type BridgeStatusSnapshot, type ClientStatus, ConsoleLogger, type ContextHash, type EmailFallbackStartOptions, type EmailFallbackVerifyOptions, type EmailFallbackVerifyResult, type EnrollOptions, type EnrollmentResult, type EventHandler, type EventPayload, type LogLevel, type Logger, type OnboardingCompleteOptions, type OnboardingCompleteResult, type OnboardingRegisterPasskeyOptions, type OnboardingRegisterPasskeyResult, type OnboardingRegisterResult, type OnboardingStartOptions, type OnboardingStartResult, type OnboardingStatusResult, type RegisterOptions, type RegisterResult, type Result, SANDBOX_SESSION_TOKEN, type SessionValidateResponse, TryMellon, type TryMellonConfig, TryMellonError, type TryMellonErrorCode, type TryMellonEvent, createError, createInvalidArgumentError, createNetworkError, createNotSupportedError, createTimeoutError, createUserCancelledError, err, isTryMellonError, mapWebAuthnError, ok };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- type TryMellonErrorCode = 'NOT_SUPPORTED' | 'USER_CANCELLED' | 'PASSKEY_NOT_FOUND' | 'SESSION_EXPIRED' | 'NETWORK_FAILURE' | 'INVALID_ARGUMENT' | 'TIMEOUT' | 'ABORTED' | 'ABORT_ERROR' | 'CHALLENGE_MISMATCH' | 'UNKNOWN_ERROR';
1
+ type TryMellonErrorCode = 'NOT_SUPPORTED' | 'USER_CANCELLED' | 'PASSKEY_NOT_FOUND' | 'SESSION_EXPIRED' | 'NETWORK_FAILURE' | 'INVALID_ARGUMENT' | 'TIMEOUT' | 'ABORTED' | 'ABORT_ERROR' | 'CHALLENGE_MISMATCH' | 'TICKET_NOT_FOUND' | 'TICKET_EXPIRED' | 'TICKET_ALREADY_USED' | 'PIN_MISMATCH' | 'PIN_LOCKED' | 'BRIDGE_SESSION_EXPIRED' | 'UNKNOWN_ERROR';
2
2
  declare class TryMellonError extends Error {
3
3
  readonly code: TryMellonErrorCode;
4
4
  readonly details?: unknown;
@@ -37,6 +37,8 @@ type Branded<T, B> = T & {
37
37
  };
38
38
  type AppId = Branded<string, 'AppId'>;
39
39
  type ExternalUserId = Branded<string, 'ExternalUserId'>;
40
+ /** 64-character hex string (SHA-256). Used to bind enrollment ticket to browser context. */
41
+ type ContextHash = Branded<string, 'ContextHash'>;
40
42
  type TryMellonConfig = {
41
43
  /** Application identifier (tenant). Required for API requests. */
42
44
  appId: string | AppId;
@@ -70,6 +72,14 @@ type TryMellonConfig = {
70
72
  * Set this in Node or when the document origin is not the correct one (e.g. SSR).
71
73
  */
72
74
  origin?: string;
75
+ /**
76
+ * Optional storage for context hash (e.g. sessionStorage). If not set, browser sessionStorage or in-memory fallback is used.
77
+ * Injected for testability and SSR; must implement getItem/setItem.
78
+ */
79
+ contextHashStorage?: {
80
+ getItem(key: string): string | null;
81
+ setItem(key: string, value: string): void;
82
+ };
73
83
  };
74
84
  interface RegisterOptions {
75
85
  /**
@@ -117,19 +127,19 @@ type SuccessEventUserInfo = {
117
127
  /** Success payload: token always present (03-eventos-seguridad). Nonce when flow generates it. */
118
128
  type SuccessEventPayload = {
119
129
  type: 'success';
120
- operation: 'register' | 'authenticate';
130
+ operation: 'register' | 'authenticate' | 'enroll';
121
131
  token: string;
122
132
  user?: SuccessEventUserInfo;
123
133
  nonce?: string;
124
134
  };
125
135
  type EventPayload = {
126
136
  type: 'start';
127
- operation: 'register' | 'authenticate';
137
+ operation: 'register' | 'authenticate' | 'enroll';
128
138
  nonce?: string;
129
139
  } | SuccessEventPayload | {
130
140
  type: 'error';
131
141
  error: TryMellonError;
132
- operation?: 'register' | 'authenticate';
142
+ operation?: 'register' | 'authenticate' | 'enroll';
133
143
  nonce?: string;
134
144
  } | {
135
145
  type: 'cancelled';
@@ -152,6 +162,31 @@ type EmailFallbackVerifyResult = {
152
162
  /** Set when successUrl was passed and allowed by application allowlist */
153
163
  redirectUrl?: string;
154
164
  };
165
+ type EnrollOptions = {
166
+ ticketId: string;
167
+ signal?: AbortSignal;
168
+ };
169
+ /** Result of finish enrollment; aligns with backend envelope (session_token). */
170
+ type EnrollmentResult = {
171
+ sessionToken: string;
172
+ };
173
+ /** Backend response for POST /v1/enrollment/register/options. Validators use this shape. */
174
+ type EnrollmentStartResponse = {
175
+ session_id: string;
176
+ challenge: RegisterStartResponse['challenge'];
177
+ };
178
+ /** Backend response for POST /v1/enrollment/register. Validators use this shape. */
179
+ type EnrollmentFinishResponse = {
180
+ credential_id: string;
181
+ status: string;
182
+ session_token: string;
183
+ user: {
184
+ user_id: string;
185
+ external_user_id?: string;
186
+ email?: string;
187
+ metadata?: Record<string, unknown>;
188
+ };
189
+ };
155
190
  type RecoveryVerifyResponse = {
156
191
  challenge: Record<string, unknown>;
157
192
  recovery_session_id: string;
@@ -288,6 +323,62 @@ type CrossDeviceVerifyRegistrationRequest = {
288
323
  session_id: string;
289
324
  credential: RegisterFinishRequest['credential'];
290
325
  };
326
+ /** Response from GET context/:sessionId (auth or registration). Aligns with backend unwrapped result. */
327
+ type BridgeContextResponse = {
328
+ type: 'auth' | 'registration';
329
+ options: Record<string, unknown>;
330
+ application_name?: string;
331
+ };
332
+ /** Response from POST verify/:sessionId (challenge / options for WebAuthn). */
333
+ type BridgeChallengeResponse = {
334
+ session_id: string;
335
+ challenge?: string;
336
+ registration_options?: Record<string, unknown>;
337
+ authentication_options?: Record<string, unknown>;
338
+ };
339
+ /** Backend result of POST complete (enrollment). Validators use this shape. */
340
+ type BridgeCompleteEnrollmentResult = {
341
+ credential_id: string;
342
+ entity_id: string;
343
+ user_id: string;
344
+ session_token: string;
345
+ };
346
+ /** Backend result of POST complete (auth). */
347
+ type BridgeCompleteAuthResult = {
348
+ session_token: string;
349
+ };
350
+ /** Options for bridge flows: PIN callback, optional preset PIN, abort signal. */
351
+ type BridgeOptions = {
352
+ onPinRequired?: () => Promise<string>;
353
+ presencePin?: string;
354
+ signal?: AbortSignal;
355
+ };
356
+ /** Public result of bridge enrollment: sessionToken and optional credential/user/entity ids. */
357
+ type BridgeEnrollmentResult = {
358
+ sessionToken: string;
359
+ credentialId?: string;
360
+ userId?: string;
361
+ entityId?: string;
362
+ };
363
+ /** Public result of bridge auth: sessionToken only. */
364
+ type BridgeAuthResult = {
365
+ sessionToken: string;
366
+ };
367
+ /** Union: bridge completion returns enrollment or auth result. */
368
+ type BridgeResult = BridgeEnrollmentResult | BridgeAuthResult;
369
+ /** Status snapshot from GET .../status/:sessionId (polling or SSE event). Terminal: pin_verified | pin_locked | completed. */
370
+ type BridgeStatusSnapshot = {
371
+ status: 'pending' | 'pin_verified' | 'pin_locked' | 'completed';
372
+ ts?: string;
373
+ };
374
+ /** Options for complete(): BridgeOptions plus kind and enrollment-only fields. */
375
+ type BridgeCompleteOptions = BridgeOptions & {
376
+ kind: 'enrollment' | 'auth';
377
+ /** Required when completing enrollment bridge. */
378
+ ticketId?: string;
379
+ /** Required when completing enrollment bridge. */
380
+ entityId?: string;
381
+ };
291
382
  type RegisterStartRequest = {
292
383
  external_user_id: string;
293
384
  };
@@ -508,6 +599,8 @@ type OnboardingRegisterResponseWithChallenge = OnboardingRegisterResponse & {
508
599
  challenge?: RegisterStartResponse['challenge'];
509
600
  };
510
601
 
602
+ /** Bridge kind: enrollment-bridge (registration flow) or auth-bridge (auth flow). */
603
+ type BridgeKind = 'enrollment' | 'auth';
511
604
  declare class ApiClient {
512
605
  private readonly httpClient;
513
606
  private readonly baseUrl;
@@ -554,6 +647,49 @@ declare class ApiClient {
554
647
  verifyCrossDeviceRegistration(request: CrossDeviceVerifyRegistrationRequest): Promise<Result<void, TryMellonError>>;
555
648
  verifyAccountRecoveryOtp(externalUserId: string, otp: string): Promise<Result<RecoveryVerifyResponse, TryMellonError>>;
556
649
  completeAccountRecovery(recoverySessionId: string, credential: Record<string, unknown>): Promise<Result<RecoveryCompleteResponse, TryMellonError>>;
650
+ startEnrollment(ticketId: string, contextHash: string, headers?: Record<string, string>): Promise<Result<EnrollmentStartResponse, TryMellonError>>;
651
+ finishEnrollment(ticketId: string, body: {
652
+ credential: unknown;
653
+ context_hash: string;
654
+ }, headers?: Record<string, string>): Promise<Result<EnrollmentFinishResponse, TryMellonError>>;
655
+ private bridgePrefix;
656
+ getBridgeContext(sessionId: string, kind: BridgeKind, headers?: Record<string, string>): Promise<Result<BridgeContextResponse, TryMellonError>>;
657
+ verifyBridgePin(sessionId: string, pin: string, kind: BridgeKind, headers?: Record<string, string>): Promise<Result<BridgeChallengeResponse, TryMellonError>>;
658
+ completeBridgeEnrollment(body: {
659
+ session_id: string;
660
+ ticket_id: string;
661
+ entity_id: string;
662
+ context_hash: string;
663
+ registration_response: {
664
+ id: string;
665
+ rawId: string;
666
+ response: {
667
+ clientDataJSON: string;
668
+ attestationObject: string;
669
+ };
670
+ type: string;
671
+ };
672
+ }, headers?: Record<string, string>): Promise<Result<BridgeCompleteEnrollmentResult, TryMellonError>>;
673
+ completeBridgeAuth(body: {
674
+ session_id: string;
675
+ credential: {
676
+ id: string;
677
+ rawId: string;
678
+ response: {
679
+ authenticatorData: string;
680
+ clientDataJSON: string;
681
+ signature: string;
682
+ userHandle?: string;
683
+ };
684
+ type: string;
685
+ };
686
+ }, headers?: Record<string, string>): Promise<Result<BridgeCompleteAuthResult, TryMellonError>>;
687
+ /**
688
+ * Full URL for GET bridge status (polling or EventSource). Same path as getBridgeStatus.
689
+ * Used by BridgeManager for SSE when EventSource is available (browser only; Node has no EventSource).
690
+ */
691
+ getBridgeStatusUrl(sessionId: string, kind: BridgeKind): string;
692
+ getBridgeStatus(sessionId: string, kind: BridgeKind, headers?: Record<string, string>): Promise<Result<BridgeStatusSnapshot, TryMellonError>>;
557
693
  }
558
694
 
559
695
  declare class OnboardingManager {
@@ -581,6 +717,9 @@ declare class TryMellon {
581
717
  private authService;
582
718
  private recoveryService;
583
719
  onboarding: OnboardingManager;
720
+ private readonly enrollmentManager;
721
+ private readonly bridgeManager;
722
+ private readonly contextHashStorage;
584
723
  /**
585
724
  * Creates a new TryMellon instance.
586
725
  * Validates config and returns a Result.
@@ -592,9 +731,25 @@ declare class TryMellon {
592
731
  * This constructor will throw errors if configuration is invalid.
593
732
  */
594
733
  constructor(config: TryMellonConfig);
734
+ /**
735
+ * Bridge (KP-BRIDGE-04): complete enrollment or auth from a second device (e.g. mobile scanning desktop QR).
736
+ * Use kind 'enrollment' for enrollment-bridge sessions, 'auth' for auth-bridge sessions.
737
+ */
738
+ get bridge(): {
739
+ getContext(sessionId: string, kind: 'enrollment' | 'auth'): Promise<Result<BridgeContextResponse, TryMellonError>>;
740
+ verifyPin(sessionId: string, pin: string, kind: 'enrollment' | 'auth'): Promise<Result<BridgeChallengeResponse, TryMellonError>>;
741
+ complete(sessionId: string, options?: BridgeCompleteOptions): Promise<Result<BridgeResult, TryMellonError>>;
742
+ waitForResult(sessionId: string, options?: {
743
+ useSse?: boolean;
744
+ kind?: 'enrollment' | 'auth';
745
+ timeoutMs?: number;
746
+ }): Promise<Result<BridgeStatusSnapshot, TryMellonError>>;
747
+ };
595
748
  static isSupported(): boolean;
596
749
  register(options: RegisterOptions): Promise<Result<RegisterResult, TryMellonError>>;
597
750
  authenticate(options: AuthenticateOptions): Promise<Result<AuthenticateResult, TryMellonError>>;
751
+ enroll(options: EnrollOptions): Promise<Result<EnrollmentResult, TryMellonError>>;
752
+ getContextHash(): string;
598
753
  validateSession(sessionToken: string): Promise<Result<SessionValidateResponse, TryMellonError>>;
599
754
  getStatus(): Promise<ClientStatus>;
600
755
  on(event: TryMellonEvent, handler: EventHandler): () => void;
@@ -636,4 +791,4 @@ declare class ConsoleLogger implements Logger {
636
791
  error(message: string, meta?: Record<string, unknown>): void;
637
792
  }
638
793
 
639
- export { type AuthenticateOptions, type AuthenticateResult, type ClientStatus, ConsoleLogger, type EmailFallbackStartOptions, type EmailFallbackVerifyOptions, type EmailFallbackVerifyResult, type EventHandler, type EventPayload, type LogLevel, type Logger, type OnboardingCompleteOptions, type OnboardingCompleteResult, type OnboardingRegisterPasskeyOptions, type OnboardingRegisterPasskeyResult, type OnboardingRegisterResult, type OnboardingStartOptions, type OnboardingStartResult, type OnboardingStatusResult, type RegisterOptions, type RegisterResult, type Result, SANDBOX_SESSION_TOKEN, type SessionValidateResponse, TryMellon, type TryMellonConfig, TryMellonError, type TryMellonErrorCode, type TryMellonEvent, createError, createInvalidArgumentError, createNetworkError, createNotSupportedError, createTimeoutError, createUserCancelledError, err, isTryMellonError, mapWebAuthnError, ok };
794
+ export { type AuthenticateOptions, type AuthenticateResult, type BridgeAuthResult, type BridgeChallengeResponse, type BridgeCompleteOptions, type BridgeContextResponse, type BridgeEnrollmentResult, type BridgeOptions, type BridgeResult, type BridgeStatusSnapshot, type ClientStatus, ConsoleLogger, type ContextHash, type EmailFallbackStartOptions, type EmailFallbackVerifyOptions, type EmailFallbackVerifyResult, type EnrollOptions, type EnrollmentResult, type EventHandler, type EventPayload, type LogLevel, type Logger, type OnboardingCompleteOptions, type OnboardingCompleteResult, type OnboardingRegisterPasskeyOptions, type OnboardingRegisterPasskeyResult, type OnboardingRegisterResult, type OnboardingStartOptions, type OnboardingStartResult, type OnboardingStatusResult, type RegisterOptions, type RegisterResult, type Result, SANDBOX_SESSION_TOKEN, type SessionValidateResponse, TryMellon, type TryMellonConfig, TryMellonError, type TryMellonErrorCode, type TryMellonEvent, createError, createInvalidArgumentError, createNetworkError, createNotSupportedError, createTimeoutError, createUserCancelledError, err, isTryMellonError, mapWebAuthnError, ok };