{"version":3,"sources":["../src/core/PasskeyManager.ts","../src/core/relayerUrl.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Passkey Manager\n * \n * Chain-agnostic WebAuthn/Passkey credential management\n */\n\nimport {\n    startRegistration,\n    startAuthentication,\n    browserSupportsWebAuthn,\n} from '@simplewebauthn/browser';\nimport type {\n    PublicKeyCredentialCreationOptionsJSON,\n    PublicKeyCredentialRequestOptionsJSON,\n    RegistrationResponseJSON,\n    AuthenticationResponseJSON,\n} from '@simplewebauthn/types';\nimport { ethers } from 'ethers';\nimport { base64URLEncode, base64URLDecode, parseDERSignature, computeKeyHash } from '../utils.js';\nimport { buildRelayerApiUrl, normalizeRelayerOrigin } from './relayerUrl.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PasskeyCredential {\n    credentialId: string;\n    publicKeyX: bigint;\n    publicKeyY: bigint;\n    keyHash: string;\n}\n\nexport interface WebAuthnSignature {\n    authenticatorData: string;\n    clientDataJSON: string;\n    challengeIndex: number;\n    typeIndex: number;\n    r: bigint;\n    s: bigint;\n}\n\nexport interface PasskeyManagerConfig {\n    rpName?: string;\n    rpId?: string;\n    timeout?: number;\n    userVerification?: 'required' | 'preferred' | 'discouraged';\n    authenticatorAttachment?: 'platform' | 'cross-platform';\n    /** Relayer API URL for cross-device credential recovery */\n    relayerUrl?: string;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * The canonical Veridex RP ID for cross-domain passkey sharing.\n * All Veridex SDK instances should use this RP ID to enable passkey\n * portability across different applications and domains.\n * \n * This works via W3C Related Origin Requests (ROR) - veridex.network\n * hosts a .well-known/webauthn file that lists allowed origins.\n */\nexport const VERIDEX_RP_ID = 'veridex.network';\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Detects the appropriate RP ID for passkey sharing.\n * \n * For production: Returns VERIDEX_RP_ID ('veridex.network') to enable\n * cross-domain passkey sharing via Related Origin Requests (ROR).\n * \n * For local development:\n * - localhost/127.0.0.1 → returns as-is\n * - IP addresses → returns as-is\n * \n * @param forceLocal - If true, uses local domain detection instead of canonical RP ID\n */\nfunction detectRpId(forceLocal?: boolean): string {\n    if (typeof window === 'undefined') return 'localhost';\n\n    const hostname = window.location.hostname;\n\n    // For local development, always use the actual hostname\n    if (hostname === 'localhost' || hostname === '127.0.0.1' || /^\\d+\\.\\d+\\.\\d+\\.\\d+$/.test(hostname)) {\n        return hostname;\n    }\n\n    // If forceLocal is true, detect from hostname (legacy behavior)\n    if (forceLocal) {\n        const parts = hostname.split('.');\n        if (parts.length <= 2) {\n            return hostname;\n        }\n        return parts.slice(-2).join('.');\n    }\n\n    // Default: Use canonical Veridex RP ID for cross-domain passkey sharing\n    return VERIDEX_RP_ID;\n}\n\n/**\n * Check if the browser supports Related Origin Requests (ROR).\n * This is a WebAuthn Level 3 feature that allows using passkeys\n * across different domains listed in the RP's .well-known/webauthn file.\n * \n * @returns true if ROR is supported, false otherwise\n */\nexport async function supportsRelatedOrigins(): Promise<boolean> {\n    if (typeof window === 'undefined' || !window.PublicKeyCredential) {\n        return false;\n    }\n\n    // Check for getClientCapabilities (WebAuthn L3)\n    if ('getClientCapabilities' in PublicKeyCredential) {\n        try {\n            const getCapabilities = (PublicKeyCredential as unknown as {\n                getClientCapabilities: () => Promise<{ relatedOrigins?: boolean }>\n            }).getClientCapabilities;\n            const capabilities = await getCapabilities();\n            return capabilities?.relatedOrigins === true;\n        } catch {\n            return false;\n        }\n    }\n\n    return false;\n}\n\n/** \n * Export the detectRpId function for external use.\n * Apps can call this to see what RP ID will be used.\n */\nexport { detectRpId };\n\n// ============================================================================\n// PasskeyManager Class\n// ============================================================================\n\n/**\n * Manages WebAuthn passkey credentials for Veridex Protocol\n */\nexport class PasskeyManager {\n    private config: Required<PasskeyManagerConfig>;\n    private credential: PasskeyCredential | null = null;\n\n    constructor(config: PasskeyManagerConfig = {}) {\n        this.config = {\n            rpName: config.rpName ?? 'Veridex Protocol',\n            rpId: config.rpId ?? detectRpId(),\n            timeout: config.timeout ?? 60000,\n            userVerification: config.userVerification ?? 'required',\n            authenticatorAttachment: config.authenticatorAttachment ?? 'platform',\n            relayerUrl: normalizeRelayerOrigin(config.relayerUrl ?? ''),\n        };\n    }\n\n    static isSupported(): boolean {\n        return browserSupportsWebAuthn();\n    }\n\n    static async isPlatformAuthenticatorAvailable(): Promise<boolean> {\n        if (typeof window === 'undefined' || !window.PublicKeyCredential) {\n            return false;\n        }\n        return await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n    }\n\n    async register(username: string, displayName: string): Promise<PasskeyCredential> {\n        if (!PasskeyManager.isSupported()) {\n            throw new Error('WebAuthn is not supported in this browser');\n        }\n\n        const challenge = ethers.randomBytes(32);\n        const challengeBase64 = base64URLEncode(challenge);\n\n        const options: PublicKeyCredentialCreationOptionsJSON = {\n            challenge: challengeBase64,\n            rp: {\n                name: this.config.rpName,\n                id: this.config.rpId,\n            },\n            user: {\n                id: base64URLEncode(ethers.toUtf8Bytes(username)),\n                name: username,\n                displayName: displayName,\n            },\n            pubKeyCredParams: [\n                { alg: -7, type: 'public-key' },   // ES256 (P-256) - WebAuthn default\n                { alg: -257, type: 'public-key' }, // RS256 - Widely supported\n                { alg: -8, type: 'public-key' },   // EdDSA - Modern, efficient\n                { alg: -35, type: 'public-key' },  // ES384 (P-384)\n                { alg: -36, type: 'public-key' },  // ES512 (P-521)\n                { alg: -37, type: 'public-key' },  // PS256 - RSA PSS\n            ],\n            authenticatorSelection: {\n                authenticatorAttachment: this.config.authenticatorAttachment,\n                userVerification: this.config.userVerification,\n                residentKey: 'required',\n                requireResidentKey: true,\n            },\n            timeout: this.config.timeout,\n            attestation: 'none',\n        };\n\n        const response = await startRegistration(options);\n        const publicKey = this.extractPublicKeyFromAttestation(response);\n        const keyHash = computeKeyHash(publicKey.x, publicKey.y);\n\n        this.credential = {\n            credentialId: response.id,\n            publicKeyX: publicKey.x,\n            publicKeyY: publicKey.y,\n            keyHash,\n        };\n\n        return this.credential;\n    }\n\n    async sign(challenge: Uint8Array): Promise<WebAuthnSignature> {\n        if (!this.credential) {\n            throw new Error('No credential set. Call register() or setCredential() first.');\n        }\n\n        const challengeBase64 = base64URLEncode(challenge);\n\n        const options: PublicKeyCredentialRequestOptionsJSON = {\n            challenge: challengeBase64,\n            rpId: this.config.rpId,\n            allowCredentials: [\n                {\n                    id: this.credential.credentialId,\n                    type: 'public-key',\n                    transports: ['internal'],\n                },\n            ],\n            userVerification: this.config.userVerification,\n            timeout: this.config.timeout,\n        };\n\n        const response = await startAuthentication(options);\n        return this.parseAuthenticationResponse(response);\n    }\n\n\n\n    /**\n     * Authenticate using a discoverable credential (passkey)\n     * This allows sign-in without knowing the credential ID ahead of time.\n     * The authenticator will show all available passkeys for this RP.\n     * \n     * @param challenge - Optional challenge bytes. If not provided, a random challenge is used.\n     * @returns The credential that was used to authenticate, along with the signature\n     */\n    async authenticate(challenge?: Uint8Array): Promise<{\n        credential: PasskeyCredential;\n        signature: WebAuthnSignature;\n    }> {\n        if (!PasskeyManager.isSupported()) {\n            throw new Error('WebAuthn is not supported in this browser');\n        }\n\n        const actualChallenge = challenge ?? ethers.randomBytes(32);\n        const challengeBase64 = base64URLEncode(actualChallenge);\n\n        // Allow any registered credential (discoverable or not)\n        const options: PublicKeyCredentialRequestOptionsJSON = {\n            challenge: challengeBase64,\n            rpId: this.config.rpId,\n            userVerification: this.config.userVerification,\n            timeout: this.config.timeout,\n        };\n\n        const response = await startAuthentication(options);\n        const credentialId = response.id;\n        const signature = this.parseAuthenticationResponse(response);\n\n        // 1. Try to find the credential in our local cache (could be one of many)\n        let storedCredential = this.findCredentialById(credentialId);\n\n        if (storedCredential) {\n            this.credential = storedCredential;\n            return { credential: storedCredential, signature };\n        }\n\n        // 2. Try to fetch from the Relayer/API if configured\n        if (this.config.relayerUrl) {\n            storedCredential = await this.loadCredentialFromRelayer(credentialId);\n            if (storedCredential) {\n                this.credential = storedCredential;\n                this.addCredentialToStorage(storedCredential);\n                return { credential: storedCredential, signature };\n            }\n        }\n\n        // 3. If we still don't have it, we can't verify signatures or derive the keyHash\n        const hasRelayer = !!this.config.relayerUrl;\n        throw new Error(\n            'Credential not found. ' +\n            'This passkey was registered on a different device or the data was cleared. ' +\n            (hasRelayer\n                ? 'The credential was not found. Please register a new passkey.'\n                : 'Please register a new passkey or ensure the relayer URL is configured.')\n        );\n    }\n\n    /**\n     * Find a credential by ID in the list of stored credentials\n     */\n    private findCredentialById(credentialId: string): PasskeyCredential | null {\n        if (typeof window === 'undefined') return null;\n\n        const stored = this.getAllStoredCredentials();\n        return stored.find(c => c.credentialId === credentialId) || null;\n    }\n\n    /**\n     * Get all credentials stored in localStorage\n     */\n    getAllStoredCredentials(key = 'veridex_credentials'): PasskeyCredential[] {\n        if (typeof window === 'undefined') return [];\n\n        const stored = localStorage.getItem(key);\n        if (!stored) {\n            // Fallback to legacy single key for backward compatibility\n            const legacy = localStorage.getItem('veridex_credential');\n            if (legacy) {\n                try {\n                    const data = JSON.parse(legacy);\n                    // Migrate to new format\n                    const cred = this.parseStoredCredential(data);\n                    if (cred) {\n                        this.saveCredentials([cred], key);\n                        localStorage.removeItem('veridex_credential');\n                        return [cred];\n                    }\n                } catch (e) { /* ignore */ }\n            }\n            return [];\n        }\n\n        try {\n            const data = JSON.parse(stored);\n            if (Array.isArray(data)) {\n                return data.map(item => this.parseStoredCredential(item)).filter((c): c is PasskeyCredential => c !== null);\n            }\n            return [];\n        } catch (error) {\n            console.error('Failed to load credentials:', error);\n            return [];\n        }\n    }\n\n    private parseStoredCredential(data: any): PasskeyCredential | null {\n        try {\n            return {\n                credentialId: data.credentialId,\n                publicKeyX: BigInt(data.publicKeyX),\n                publicKeyY: BigInt(data.publicKeyY),\n                keyHash: data.keyHash,\n            };\n        } catch {\n            return null;\n        }\n    }\n\n    /**\n     * Save a list of credentials to localStorage\n     */\n    saveCredentials(credentials: PasskeyCredential[], key = 'veridex_credentials'): void {\n        if (typeof window === 'undefined') return;\n\n        const data = credentials.map(c => ({\n            credentialId: c.credentialId,\n            publicKeyX: c.publicKeyX.toString(),\n            publicKeyY: c.publicKeyY.toString(),\n            keyHash: c.keyHash,\n        }));\n\n        localStorage.setItem(key, JSON.stringify(data));\n    }\n\n    /**\n     * Add a single credential to storage (append or update)\n     */\n    addCredentialToStorage(credential: PasskeyCredential, key = 'veridex_credentials'): void {\n        const stored = this.getAllStoredCredentials(key);\n        const existingIndex = stored.findIndex(c => c.credentialId === credential.credentialId);\n\n        if (existingIndex >= 0) {\n            stored[existingIndex] = credential;\n        } else {\n            stored.push(credential);\n        }\n\n        this.saveCredentials(stored, key);\n    }\n\n    /**\n     * Check if there's ANY stored credential for this RP\n     */\n    hasStoredCredential(): boolean {\n        return this.getAllStoredCredentials().length > 0;\n    }\n\n    getCredential(): PasskeyCredential | null {\n        return this.credential;\n    }\n\n    setCredential(credential: PasskeyCredential): void {\n        this.credential = credential;\n    }\n\n    createCredentialFromPublicKey(\n        credentialId: string,\n        publicKeyX: bigint,\n        publicKeyY: bigint\n    ): PasskeyCredential {\n        const keyHash = computeKeyHash(publicKeyX, publicKeyY);\n        this.credential = {\n            credentialId,\n            publicKeyX,\n            publicKeyY,\n            keyHash,\n        };\n        return this.credential;\n    }\n\n    clearCredential(): void {\n        this.credential = null;\n    }\n\n    /**\n     * Save the current credential to localStorage (appends to list)\n     */\n    saveToLocalStorage(key = 'veridex_credentials'): void {\n        if (!this.credential) {\n            throw new Error('No credential to save');\n        }\n        this.addCredentialToStorage(this.credential, key);\n    }\n\n    loadFromLocalStorage(key = 'veridex_credentials'): PasskeyCredential | null {\n        if (typeof window === 'undefined') {\n            return null;\n        }\n\n        // Return the most recently used credential, or the last one added\n        const stored = this.getAllStoredCredentials(key);\n        if (stored.length > 0) {\n            // Use the last one as default\n            this.credential = stored[stored.length - 1];\n            return this.credential;\n        }\n\n        return null;\n    }\n\n    removeFromLocalStorage(key = 'veridex_credentials'): void {\n        if (typeof window !== 'undefined') {\n            localStorage.removeItem(key);\n            // Also remove legacy key\n            localStorage.removeItem('veridex_credential');\n        }\n    }\n\n    // =========================================================================\n    // Relayer-based Credential Storage (Cross-Device Recovery)\n    // =========================================================================\n\n    /**\n     * Save the current credential to the relayer for cross-device recovery.\n     * This should be called after registration.\n     */\n    async saveCredentialToRelayer(): Promise<boolean> {\n        if (!this.credential) {\n            throw new Error('No credential to save');\n        }\n        if (!this.config.relayerUrl) {\n            console.warn('Relayer URL not configured; skipping remote credential storage');\n            return false;\n        }\n\n        try {\n            const response = await fetch(buildRelayerApiUrl(this.config.relayerUrl, '/credential'), {\n                method: 'POST',\n                headers: { 'Content-Type': 'application/json' },\n                body: JSON.stringify({\n                    keyHash: this.credential.keyHash,\n                    credentialId: this.credential.credentialId,\n                    publicKeyX: this.credential.publicKeyX.toString(),\n                    publicKeyY: this.credential.publicKeyY.toString(),\n                }),\n            });\n\n            if (!response.ok) {\n                const errorData = await response.json().catch(() => ({}));\n                console.error('Failed to save credential to relayer:', errorData);\n                return false;\n            }\n\n            console.log('Credential saved to relayer for cross-device recovery');\n            return true;\n        } catch (error) {\n            console.error('Failed to save credential to relayer:', error);\n            return false;\n        }\n    }\n\n    /**\n     * Load a credential from the relayer by credential ID.\n     * Used during discoverable credential authentication when localStorage is empty.\n     */\n    async loadCredentialFromRelayer(credentialId: string): Promise<PasskeyCredential | null> {\n        if (!this.config.relayerUrl) {\n            return null;\n        }\n\n        try {\n            const response = await fetch(\n                buildRelayerApiUrl(this.config.relayerUrl, `/credential/by-id/${encodeURIComponent(credentialId)}`)\n            );\n\n            if (!response.ok) {\n                return null;\n            }\n\n            const data = await response.json();\n            if (!data.exists) {\n                return null;\n            }\n\n            // Validate required fields before attempting BigInt conversion\n            if (!data.credentialId || !data.publicKeyX || !data.publicKeyY || !data.keyHash) {\n                console.warn('Relayer returned incomplete credential data:', {\n                    hasCredentialId: !!data.credentialId,\n                    hasPublicKeyX: !!data.publicKeyX,\n                    hasPublicKeyY: !!data.publicKeyY,\n                    hasKeyHash: !!data.keyHash,\n                });\n                return null;\n            }\n\n            return {\n                credentialId: data.credentialId,\n                publicKeyX: BigInt(data.publicKeyX),\n                publicKeyY: BigInt(data.publicKeyY),\n                keyHash: data.keyHash,\n            };\n        } catch (error) {\n            console.error('Failed to load credential from relayer:', error);\n            return null;\n        }\n    }\n\n    /**\n     * Load a credential from the relayer by keyHash.\n     * Useful when you know the user's keyHash but not their credential ID.\n     */\n    async loadCredentialFromRelayerByKeyHash(keyHash: string): Promise<PasskeyCredential | null> {\n        if (!this.config.relayerUrl) {\n            return null;\n        }\n\n        try {\n            const response = await fetch(\n                buildRelayerApiUrl(this.config.relayerUrl, `/credential/${encodeURIComponent(keyHash)}`)\n            );\n\n            if (!response.ok) {\n                return null;\n            }\n\n            const data = await response.json();\n            if (!data.exists) {\n                return null;\n            }\n\n            // Validate required fields before attempting BigInt conversion\n            if (!data.credentialId || !data.publicKeyX || !data.publicKeyY || !data.keyHash) {\n                console.warn('Relayer returned incomplete credential data for keyHash:', {\n                    hasCredentialId: !!data.credentialId,\n                    hasPublicKeyX: !!data.publicKeyX,\n                    hasPublicKeyY: !!data.publicKeyY,\n                    hasKeyHash: !!data.keyHash,\n                });\n                return null;\n            }\n\n            return {\n                credentialId: data.credentialId,\n                publicKeyX: BigInt(data.publicKeyX),\n                publicKeyY: BigInt(data.publicKeyY),\n                keyHash: data.keyHash,\n            };\n        } catch (error) {\n            console.error('Failed to load credential from relayer:', error);\n            return null;\n        }\n    }\n\n    // =========================================================================\n    // Backup Passkey & Device Migration (Phase 3)\n    // =========================================================================\n\n    /**\n     * Register a backup passkey for the current identity.\n     *\n     * This creates a new WebAuthn credential on this device/platform that becomes\n     * an additional authorized key for the same Veridex identity. The caller\n     * must submit the returned credential to VeridexHub.addKey() for on-chain registration.\n     *\n     * Use cases:\n     * - \"Add this device\" flow when signing in on a new machine\n     * - Proactive backup creation on a separate authenticator\n     * - Cross-ecosystem redundancy (iCloud + Google Password Manager)\n     *\n     * @param username - Username for the new credential (typically same as primary)\n     * @param displayName - Display name for the backup (e.g., \"MacBook Pro Backup\")\n     * @param excludeCredentialIds - Credential IDs to exclude (prevents re-registering same authenticator)\n     * @returns The newly registered backup credential\n     */\n    async registerBackupPasskey(\n        username: string,\n        displayName: string,\n        excludeCredentialIds?: string[]\n    ): Promise<PasskeyCredential> {\n        if (!PasskeyManager.isSupported()) {\n            throw new Error('WebAuthn is not supported in this browser');\n        }\n\n        const challenge = ethers.randomBytes(32);\n        const challengeBase64 = base64URLEncode(challenge);\n\n        // Build exclude list: prevent re-registering on the same authenticator\n        const excludeList = excludeCredentialIds ?? this.getAllStoredCredentials().map(c => c.credentialId);\n\n        const options: PublicKeyCredentialCreationOptionsJSON = {\n            challenge: challengeBase64,\n            rp: {\n                name: this.config.rpName,\n                id: this.config.rpId,\n            },\n            user: {\n                id: base64URLEncode(ethers.toUtf8Bytes(username)),\n                name: username,\n                displayName: displayName,\n            },\n            pubKeyCredParams: [\n                { alg: -7, type: 'public-key' },   // ES256 (P-256)\n                { alg: -257, type: 'public-key' },  // RS256\n                { alg: -8, type: 'public-key' },    // EdDSA\n            ],\n            excludeCredentials: excludeList.map(id => ({\n                id,\n                type: 'public-key' as const,\n                transports: ['internal' as const, 'hybrid' as const],\n            })),\n            authenticatorSelection: {\n                // Allow cross-platform for backup on security keys\n                userVerification: this.config.userVerification,\n                residentKey: 'required',\n                requireResidentKey: true,\n            },\n            timeout: this.config.timeout,\n            attestation: 'none',\n        };\n\n        const response = await startRegistration(options);\n        const publicKey = this.extractPublicKeyFromAttestation(response);\n        const keyHash = computeKeyHash(publicKey.x, publicKey.y);\n\n        const backupCredential: PasskeyCredential = {\n            credentialId: response.id,\n            publicKeyX: publicKey.x,\n            publicKeyY: publicKey.y,\n            keyHash,\n        };\n\n        // Store locally alongside existing credentials\n        this.addCredentialToStorage(backupCredential);\n\n        return backupCredential;\n    }\n\n    /**\n     * Get registration info for backup state from a registration response.\n     *\n     * This extracts the backup eligibility (BE) and backup state (BS) flags\n     * from the authenticator data, which indicate whether the credential\n     * is eligible for cloud sync and whether it is currently synced.\n     *\n     * @param authenticatorData - Hex-encoded authenticator data from registration\n     * @returns Backup flags, or null if not determinable\n     */\n    static parseBackupFlags(authenticatorData: string): {\n        backupEligible: boolean;\n        backupState: boolean;\n    } | null {\n        try {\n            const data = ethers.getBytes(authenticatorData);\n            if (data.length < 37) return null;\n\n            // Flags byte is at offset 32 (after the 32-byte rpIdHash)\n            const flags = data[32];\n\n            // Bit 3 (0x08) = Backup Eligible (BE)\n            // Bit 4 (0x10) = Backup State (BS)\n            return {\n                backupEligible: (flags & 0x08) !== 0,\n                backupState: (flags & 0x10) !== 0,\n            };\n        } catch {\n            return null;\n        }\n    }\n\n    /**\n     * Get the number of credentials stored locally.\n     */\n    getStoredCredentialCount(): number {\n        return this.getAllStoredCredentials().length;\n    }\n\n    /**\n     * Get all credential IDs stored locally (for exclude lists).\n     */\n    getStoredCredentialIds(): string[] {\n        return this.getAllStoredCredentials().map(c => c.credentialId);\n    }\n\n    private extractPublicKeyFromAttestation(\n        response: RegistrationResponseJSON\n    ): { x: bigint; y: bigint } {\n        const attestationObject = base64URLDecode(response.response.attestationObject);\n\n        // Parse CBOR attestation object\n        // The attestation object is a CBOR map with keys: fmt, authData, attStmt\n        // We need to extract the authData which contains the credential public key\n\n        let offset = 0;\n\n        // Skip the CBOR map header (usually 0xa3 for 3-item map or 0xa2 for 2-item map)\n        if (attestationObject[offset] >= 0xa0 && attestationObject[offset] <= 0xbf) {\n            offset++;\n        }\n\n        // Find the authData field in the CBOR map\n        // Look for the text string \"authData\" (0x68 followed by \"authData\")\n        while (offset < attestationObject.length - 37) {\n            if (attestationObject[offset] === 0x68 && // text string, 8 bytes\n                attestationObject[offset + 1] === 0x61 && // 'a'\n                attestationObject[offset + 2] === 0x75 && // 'u'\n                attestationObject[offset + 3] === 0x74 && // 't'\n                attestationObject[offset + 4] === 0x68 && // 'h'\n                attestationObject[offset + 5] === 0x44 && // 'D'\n                attestationObject[offset + 6] === 0x61 && // 'a'\n                attestationObject[offset + 7] === 0x74 && // 't'\n                attestationObject[offset + 8] === 0x61) { // 'a'\n                offset += 9;\n                break;\n            }\n            offset++;\n        }\n\n        // Skip the byte string header for authData\n        if (attestationObject[offset] === 0x58 || attestationObject[offset] === 0x59) {\n            // 0x58 = 1-byte length, 0x59 = 2-byte length\n            const lengthBytes = attestationObject[offset] === 0x58 ? 1 : 2;\n            offset += 1 + lengthBytes;\n        }\n\n        // Now we're at the start of authData\n        // authData structure:\n        // - rpIdHash: 32 bytes\n        // - flags: 1 byte\n        // - signCount: 4 bytes\n        // - attestedCredentialData (if AT flag is set):\n        //   - aaguid: 16 bytes\n        //   - credentialIdLength: 2 bytes\n        //   - credentialId: credentialIdLength bytes\n        //   - credentialPublicKey: CBOR-encoded COSE_Key\n\n        offset += 32; // Skip rpIdHash\n        offset += 1;  // Skip flags\n        offset += 4;  // Skip signCount\n        offset += 16; // Skip aaguid\n\n        // Read credential ID length\n        const credIdLen = (attestationObject[offset] << 8) | attestationObject[offset + 1];\n        offset += 2;\n        offset += credIdLen; // Skip credential ID\n\n        // Now we're at the COSE public key\n        const coseKey = attestationObject.slice(offset);\n\n        console.log('COSE key length:', coseKey.length);\n        console.log('COSE key hex:', this.bytesToHex(coseKey.slice(0, Math.min(100, coseKey.length))));\n\n        const { x, y } = this.parseCOSEKey(coseKey);\n        return { x, y };\n    }\n\n    private parseCOSEKey(coseKey: Uint8Array): { x: bigint; y: bigint } {\n        console.log('COSE key length:', coseKey.length);\n        console.log('COSE key hex:', this.bytesToHex(coseKey));\n\n        // Try multiple parsing strategies\n        const parsed = this.tryParseCOSEKeyStrategies(coseKey);\n        if (parsed) {\n            return parsed;\n        }\n\n        // If all strategies fail, try using a CBOR parser approach\n        return this.parseCOSEKeyWithCBORStructure(coseKey);\n    }\n\n    private tryParseCOSEKeyStrategies(coseKey: Uint8Array): { x: bigint; y: bigint } | null {\n        // Strategy 1: Look for the specific pattern of EC2 keys\n        const keyBytes = new Uint8Array(coseKey);\n\n        // Common pattern for EC2 keys with P-256 curve\n        for (let i = 0; i < keyBytes.length - 40; i++) {\n            // Check for potential x coordinate (32 bytes preceded by key marker)\n            if (keyBytes[i] === 0x58 && keyBytes[i + 1] === 0x20) {\n                const potentialX = keyBytes.slice(i + 2, i + 34);\n\n                // Look for y coordinate after x\n                for (let j = i + 34; j < keyBytes.length - 34; j++) {\n                    if (keyBytes[j] === 0x58 && keyBytes[j + 1] === 0x20) {\n                        const potentialY = keyBytes.slice(j + 2, j + 34);\n\n                        // Verify these look like valid coordinates\n                        if (this.isValidCoordinate(potentialX) && this.isValidCoordinate(potentialY)) {\n                            console.log('Found coordinates via pattern matching');\n                            return {\n                                x: this.bytesToBigInt(potentialX),\n                                y: this.bytesToBigInt(potentialY)\n                            };\n                        }\n                    }\n                }\n            }\n        }\n\n        // Strategy 2: Look for ASN.1 structure\n        return this.tryParseASN1Structure(keyBytes);\n    }\n\n    private parseCOSEKeyWithCBORStructure(coseKey: Uint8Array): { x: bigint; y: bigint } {\n        // More flexible parsing that handles different CBOR structures\n        const bytes = new Uint8Array(coseKey);\n        let xBytes: Uint8Array | null = null;\n        let yBytes: Uint8Array | null = null;\n\n        // Look for x and y coordinates by scanning for byte strings\n        let i = 0;\n        while (i < bytes.length) {\n            // Check for byte string markers\n            if (bytes[i] === 0x58) { // Byte string with length byte\n                const length = bytes[i + 1];\n                if (length === 0x20) { // 32 bytes - likely a coordinate\n                    const start = i + 2;\n                    const end = start + 32;\n\n                    if (end <= bytes.length) {\n                        const coordinate = bytes.slice(start, end);\n\n                        // Assign to x or y based on position or previous assignments\n                        if (!xBytes) {\n                            xBytes = coordinate;\n                            console.log('Found x at offset', i);\n                        } else if (!yBytes) {\n                            yBytes = coordinate;\n                            console.log('Found y at offset', i);\n                            break; // Found both, exit loop\n                        }\n                    }\n                    i = end;\n                } else {\n                    i += length + 2;\n                }\n            } else if (bytes[i] === 0x42) { // Byte string with 2-byte length\n                if (i + 3 < bytes.length) {\n                    const length = (bytes[i + 1] << 8) | bytes[i + 2];\n                    if (length === 32) {\n                        const start = i + 3;\n                        const end = start + 32;\n\n                        if (end <= bytes.length) {\n                            const coordinate = bytes.slice(start, end);\n\n                            if (!xBytes) {\n                                xBytes = coordinate;\n                                console.log('Found x at offset', i);\n                            } else if (!yBytes) {\n                                yBytes = coordinate;\n                                console.log('Found y at offset', i);\n                                break;\n                            }\n                        }\n                        i = end;\n                    } else {\n                        i += length + 3;\n                    }\n                } else {\n                    i++;\n                }\n            } else if (bytes[i] === 0x40) { // Byte string with indefinite length\n                // Skip indefinite length marker\n                i++;\n                // Look for 0x04 marker (uncompressed point) or direct coordinates\n                while (i < bytes.length && bytes[i] !== 0xFF) { // 0xFF is break marker\n                    if (bytes[i] === 0x04 && i + 65 <= bytes.length) {\n                        // Uncompressed EC point format\n                        const x = bytes.slice(i + 1, i + 33);\n                        const y = bytes.slice(i + 33, i + 65);\n\n                        if (this.isValidCoordinate(x) && this.isValidCoordinate(y)) {\n                            xBytes = x;\n                            yBytes = y;\n                            console.log('Found coordinates in uncompressed point format');\n                            break;\n                        }\n                    }\n                    i++;\n                }\n                if (xBytes && yBytes) break;\n            } else {\n                i++;\n            }\n        }\n\n        if (!xBytes || !yBytes) {\n            // Fallback: Try to find any 32-byte sequences\n            const potentialCoords = this.find32ByteSequences(bytes);\n            if (potentialCoords.length >= 2) {\n                xBytes = potentialCoords[0];\n                yBytes = potentialCoords[1];\n                console.log('Fallback: Using first two 32-byte sequences as coordinates');\n            }\n        }\n\n        if (!xBytes || !yBytes) {\n            console.error('Failed to find coordinates in COSE key. Full dump:');\n            console.error('Hex:', this.bytesToHex(bytes));\n            console.error('Structure analysis:');\n            this.analyzeCOSEStructure(bytes);\n            throw new Error('Failed to extract public key coordinates from COSE key. Check console for details.');\n        }\n\n        return {\n            x: this.bytesToBigInt(xBytes),\n            y: this.bytesToBigInt(yBytes)\n        };\n    }\n\n    private tryParseASN1Structure(bytes: Uint8Array): { x: bigint; y: bigint } | null {\n        // ASN.1 SEQUENCE for EC public key\n        if (bytes[0] === 0x30) { // SEQUENCE tag\n            let offset = 2; // Skip tag and length\n\n            // Look for BIT STRING (0x03)\n            if (bytes[offset] === 0x03) {\n                offset += 2; // Skip BIT STRING tag and unused bits\n\n                // Look for another SEQUENCE\n                if (bytes[offset] === 0x30) {\n                    offset += 2;\n\n                    // Should now have OID for P-256: 1.2.840.10045.3.1.7\n                    // Skip OID (usually 10 bytes: 06 08 2A 86 48 CE 3D 03 01 07)\n                    offset += 12;\n\n                    // BIT STRING containing the raw public key\n                    if (bytes[offset] === 0x03 && bytes[offset + 2] === 0x04) {\n                        offset += 3; // Skip to uncompressed point (0x04)\n\n                        const x = bytes.slice(offset, offset + 32);\n                        const y = bytes.slice(offset + 32, offset + 64);\n\n                        if (x.length === 32 && y.length === 32) {\n                            console.log('Found coordinates via ASN.1 parsing');\n                            return {\n                                x: this.bytesToBigInt(x),\n                                y: this.bytesToBigInt(y)\n                            };\n                        }\n                    }\n                }\n            }\n        }\n        return null;\n    }\n\n    private find32ByteSequences(bytes: Uint8Array): Uint8Array[] {\n        const sequences: Uint8Array[] = [];\n\n        for (let i = 0; i <= bytes.length - 32; i++) {\n            // Check if this 32-byte sequence looks like a valid coordinate\n            const sequence = bytes.slice(i, i + 32);\n            if (this.isValidCoordinate(sequence)) {\n                sequences.push(sequence);\n            }\n        }\n\n        return sequences;\n    }\n\n    private isValidCoordinate(bytes: Uint8Array): boolean {\n        if (bytes.length !== 32) return false;\n\n        // Basic validation: not all zeros, not all FF\n        let allZeros = true;\n        let allOnes = true;\n\n        for (const byte of bytes) {\n            if (byte !== 0) allZeros = false;\n            if (byte !== 0xFF) allOnes = false;\n        }\n\n        return !allZeros && !allOnes;\n    }\n\n    private bytesToBigInt(bytes: Uint8Array): bigint {\n        return BigInt('0x' + this.bytesToHex(bytes));\n    }\n\n    private bytesToHex(bytes: Uint8Array): string {\n        return Array.from(bytes)\n            .map(b => b.toString(16).padStart(2, '0'))\n            .join('');\n    }\n\n    private analyzeCOSEStructure(bytes: Uint8Array): void {\n        console.log('COSE Structure Analysis:');\n        console.log('First 20 bytes:', this.bytesToHex(bytes.slice(0, 20)));\n\n        // Check for known COSE key structure markers\n        const firstByte = bytes[0];\n        console.log('First byte (0x' + firstByte.toString(16) + '):');\n\n        if (firstByte >= 0xa0 && firstByte <= 0xbf) {\n            console.log('- Definite length map with', (firstByte & 0x1f), 'pairs');\n        } else if (firstByte === 0xbf) {\n            console.log('- Indefinite length map');\n        } else if (firstByte === 0x04) {\n            console.log('- Byte string');\n        } else if (firstByte === 0x02) {\n            console.log('- Negative integer');\n        }\n\n        // Count occurrences of 32-byte sequences\n        let count32 = 0;\n        for (let i = 0; i <= bytes.length - 32; i++) {\n            const chunk = bytes.slice(i, i + 32);\n            if (this.isValidCoordinate(chunk)) {\n                console.log(`Found valid 32-byte sequence at offset ${i}:`,\n                    this.bytesToHex(chunk.slice(0, 8)) + '...');\n                count32++;\n            }\n        }\n        console.log(`Total valid 32-byte sequences: ${count32}`);\n\n        // Look for specific markers\n        console.log('Looking for known markers:');\n        const markers = [\n            { byte: 0x04, name: 'Uncompressed point marker' },\n            { byte: 0x03, name: 'BIT STRING' },\n            { byte: 0x30, name: 'SEQUENCE' },\n            { byte: 0x02, name: 'INTEGER' },\n            { byte: 0x06, name: 'OBJECT IDENTIFIER' },\n            { byte: 0x58, name: 'Byte string with length byte' },\n            { byte: 0x42, name: 'Byte string with 2-byte length' },\n            { byte: 0x40, name: 'Byte string indefinite length' },\n            { byte: 0xA0, name: 'Map start' },\n            { byte: 0xBF, name: 'Indefinite map start' },\n        ];\n\n        for (const marker of markers) {\n            const indices = [];\n            for (let i = 0; i < bytes.length; i++) {\n                if (bytes[i] === marker.byte) {\n                    indices.push(i);\n                }\n            }\n            if (indices.length > 0) {\n                console.log(`  ${marker.name} (0x${marker.byte.toString(16)}) at positions:`, indices.slice(0, 5).join(', '));\n            }\n        }\n    }\n\n    private parseAuthenticationResponse(response: AuthenticationResponseJSON): WebAuthnSignature {\n        const authenticatorData = base64URLDecode(response.response.authenticatorData);\n        const clientDataJSON = response.response.clientDataJSON;\n        const signature = base64URLDecode(response.response.signature);\n\n        const { r, s } = parseDERSignature(signature);\n\n        // Normalize signature to low-S form.\n        // The on-chain WebAuthn verifier rejects signatures with s > n/2.\n        // WebAuthn authenticators are not guaranteed to produce low-S signatures,\n        // so without this normalization, valid signatures can intermittently fail.\n        const P256_N = BigInt('0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551');\n        const P256_N_DIV_2 = BigInt(\n            '0x7FFFFFFF800000007FFFFFFFFFFFFFFFDE737D56D38BCF4279DCE5617E3192A8'\n        );\n\n        const clientDataStr = new TextDecoder().decode(base64URLDecode(clientDataJSON));\n        const challengeIndex = clientDataStr.indexOf('\"challenge\"');\n        const typeIndex = clientDataStr.indexOf('\"type\"');\n\n        if (challengeIndex === -1 || typeIndex === -1) {\n            throw new Error('Invalid clientDataJSON format');\n        }\n\n        return {\n            authenticatorData: ethers.hexlify(authenticatorData),\n            clientDataJSON: clientDataStr,\n            challengeIndex,\n            typeIndex,\n            r: this.bytesToBigInt(r),\n            s: (() => {\n                const sBig = this.bytesToBigInt(s);\n                return sBig > P256_N_DIV_2 ? P256_N - sBig : sBig;\n            })(),\n        };\n    }\n}\n","const API_ROOT = '/api/v1';\n\nfunction trimTrailingSlashes(value: string): string {\n    return value.trim().replace(/\\/+$/, '');\n}\n\nexport function normalizeRelayerOrigin(value: string): string {\n    const trimmed = trimTrailingSlashes(value);\n    if (!trimmed) {\n        return '';\n    }\n\n    if (trimmed.startsWith('/')) {\n        return trimmed.replace(/\\/api\\/v1$/i, '');\n    }\n\n    try {\n        const url = new URL(trimmed);\n        url.pathname = url.pathname.replace(/\\/api\\/v1$/i, '').replace(/\\/+$/, '');\n        return url.toString().replace(/\\/+$/, '');\n    } catch {\n        return trimmed.replace(/\\/api\\/v1$/i, '');\n    }\n}\n\nexport function buildRelayerApiUrl(baseUrl: string, path: string): string {\n    const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n    const trimmed = trimTrailingSlashes(baseUrl);\n\n    if (!trimmed) {\n        return `${API_ROOT}${normalizedPath}`;\n    }\n\n    if (trimmed.startsWith('/')) {\n        if (/\\/api\\/v1$/i.test(trimmed) || /\\/api\\/auth\\/relay$/i.test(trimmed)) {\n            return `${trimmed}${normalizedPath}`;\n        }\n\n        return `${trimmed}${normalizedPath}`;\n    }\n\n    try {\n        const url = new URL(trimmed);\n\n        if (/\\/api\\/v1$/i.test(url.pathname) || /\\/api\\/auth\\/relay$/i.test(url.pathname)) {\n            url.pathname = `${url.pathname.replace(/\\/+$/, '')}${normalizedPath}`;\n            return url.toString();\n        }\n\n        if (!url.pathname || url.pathname === '/') {\n            url.pathname = `${API_ROOT}${normalizedPath}`;\n            return url.toString();\n        }\n\n        url.pathname = `${url.pathname.replace(/\\/+$/, '')}${normalizedPath}`;\n        return url.toString();\n    } catch {\n        if (/\\/api\\/v1$/i.test(trimmed) || /\\/api\\/auth\\/relay$/i.test(trimmed)) {\n            return `${trimmed}${normalizedPath}`;\n        }\n\n        return `${trimmed}${API_ROOT}${normalizedPath}`;\n    }\n}\n"],"mappings":"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","names":[]}