import type { z } from 'zod' import type React from 'react' export type MfaMethodRecord = { id: string type: string userId: string tenantId?: string organizationId?: string | null secret?: string | null providerMetadata?: Record | null } export type MfaProviderConfirmResult = { metadata: Record secret?: string | null } export type MfaVerifyContext = { challenge?: Record | null } export type MfaProviderRuntimeContext = { request?: Request } export type MfaProviderUser = { id: string email?: string | null tenantId: string organizationId?: string | null } export interface MfaSetupComponentProps { clientData: Record onConfirm: (payload: unknown) => Promise onCancel: () => void } export interface MfaVerifyComponentProps { clientData?: Record onVerify: (payload: unknown) => Promise onCancel: () => void onResend?: () => Promise } export interface MfaProviderInterface { readonly type: string readonly label: string readonly icon: string readonly allowMultiple: boolean readonly setupSchema: z.ZodSchema readonly verifySchema: z.ZodSchema resolveSetupPayload?(user: MfaProviderUser, payload: unknown): Promise | unknown setup( userId: string, payload: unknown, context?: MfaProviderRuntimeContext, ): Promise<{ setupId: string; clientData: Record }> confirmSetup( userId: string, setupId: string, payload: unknown, context?: MfaProviderRuntimeContext, ): Promise prepareChallenge( userId: string, method: MfaMethodRecord, context?: MfaProviderRuntimeContext, ): Promise<{ clientData?: Record; verifyContext?: MfaVerifyContext }> verify( userId: string, method: MfaMethodRecord, payload: unknown, context?: MfaVerifyContext, runtimeContext?: MfaProviderRuntimeContext, ): Promise } export type MfaProviderComponents = { setup?: string list?: string details?: string challenge?: string } export type MfaProviderSetup = MfaProviderInterface & { readonly components?: MfaProviderComponents } export function buildMfaProviderComponentHandles(providerType: string): Required { return { setup: `section:security.mfa.setup.provider:${providerType}`, list: `section:security.mfa.providers.list-item:${providerType}`, details: `section:security.mfa.provider.details:${providerType}`, challenge: `section:security.mfa.challenge.provider:${providerType}`, } } export function createMfaProviderSetup( provider: MfaProviderInterface, components?: MfaProviderComponents, ): MfaProviderSetup { return { type: provider.type, label: provider.label, icon: provider.icon, allowMultiple: provider.allowMultiple, setupSchema: provider.setupSchema, verifySchema: provider.verifySchema, resolveSetupPayload: provider.resolveSetupPayload?.bind(provider), setup: provider.setup.bind(provider), confirmSetup: provider.confirmSetup.bind(provider), prepareChallenge: provider.prepareChallenge.bind(provider), verify: provider.verify.bind(provider), components, } } export function isMfaProviderSetup(value: unknown): value is MfaProviderSetup { if (!value || typeof value !== 'object') return false const candidate = value as Partial return typeof candidate.type === 'string' && typeof candidate.label === 'string' && typeof candidate.icon === 'string' && typeof candidate.allowMultiple === 'boolean' && typeof candidate.setup === 'function' && typeof candidate.confirmSetup === 'function' && typeof candidate.prepareChallenge === 'function' && typeof candidate.verify === 'function' }