/** * Message types for PostMessage communication between iframe and parent window */ declare const MESSAGE_TYPES: { readonly READY: "READY"; readonly HANDSHAKE: "HANDSHAKE"; readonly HANDSHAKE_ACK: "HANDSHAKE_ACK"; readonly ACTION_REQUEST: "ACTION_REQUEST"; readonly URL_REDIRECT: "URL_REDIRECT"; readonly GET_ACCOUNTS: "GET_ACCOUNTS"; readonly ACCOUNTS_DATA: "ACCOUNTS_DATA"; readonly SWITCH_ACCOUNT: "SWITCH_ACCOUNT"; readonly ACCOUNT_SWITCHED: "ACCOUNT_SWITCHED"; readonly ADD_ACCOUNT: "ADD_ACCOUNT"; readonly ACCOUNT_ADDED: "ACCOUNT_ADDED"; readonly ADD_ACCOUNT_WITH_TOKEN: "ADD_ACCOUNT_WITH_TOKEN"; readonly ADD_ACCOUNT_WITH_TOKEN_OK: "ADD_ACCOUNT_WITH_TOKEN_OK"; readonly ADD_ACCOUNT_WITH_TOKEN_FAILED: "ADD_ACCOUNT_WITH_TOKEN_FAILED"; readonly PREP_SIGNED: "prep-signed"; readonly PREP_SIGN_FAILED: "prep-sign-failed"; readonly MANAGE_ACCOUNT: "MANAGE_ACCOUNT"; readonly UPDATE_AVATAR: "UPDATE_AVATAR"; readonly LOGOUT_ACCOUNT: "LOGOUT_ACCOUNT"; readonly ACCOUNT_LOGGED_OUT: "ACCOUNT_LOGGED_OUT"; readonly LOGOUT_ALL: "LOGOUT_ALL"; readonly ALL_LOGGED_OUT: "ALL_LOGGED_OUT"; readonly CONFIRM_REQUEST: "CONFIRM_REQUEST"; readonly PROMPT_REQUEST: "PROMPT_REQUEST"; readonly ALERT_REQUEST: "ALERT_REQUEST"; readonly REQUEST_RESPONSE: "REQUEST_RESPONSE"; readonly SESSION_CHANGED: "SESSION_CHANGED"; readonly TOKEN_REFRESHED: "TOKEN_REFRESHED"; readonly SIZE_CHANGED: "SIZE_CHANGED"; readonly SET_SESSION: "SET_SESSION"; readonly SESSION_SET: "SESSION_SET"; readonly SET_PAGE_URL: "SET_PAGE_URL"; readonly ERROR: "ERROR"; readonly UNAUTHORIZED: "UNAUTHORIZED"; }; /** * PostMessage message structure */ interface PostMessageData { type: string; payload?: any; requestId?: string; timestamp?: number; version?: string; } /** * Session change event payload */ interface SessionChangedPayload { isAuthenticated: boolean; currentUser: any; accounts: any[]; } /** * Account switched event payload */ interface AccountSwitchedPayload { uuid: string; name: string; email: string; avatar_url?: string; } /** * Error event payload */ interface ErrorPayload { message: string; code?: string; details?: any; } /** * Resize event payload */ interface ResizePayload { height: number; } /** * Action request payload (Unified Action Protocol) */ interface ActionRequestPayload { action: string; params: Record; } /** * URL redirect payload (Unified Action Protocol) */ interface UrlRedirectPayload { url: string; reason?: string; openInNewTab?: boolean; } /** * Sharing protocol — request payload sent by `multiAccountAutoAdd` (F4) to the * auth-service iframe (A6). The iframe redeems the session token at its own * backend, writes the destination-scoped session cookie, and acks with * ADD_ACCOUNT_WITH_TOKEN_OK (or ..._FAILED). */ interface AddAccountWithTokenPayload { /** UUID of the user being added — must match the user the session token was issued for. */ accountUuid: string; /** Short-lived session token returned by the handoff exchange (F1). */ sessionToken: string; } /** * Sharing protocol — iframe → host: cookie written and account appended. */ interface AddAccountWithTokenOkPayload { accountUuid: string; } /** * Sharing protocol — iframe → host: redemption failed. * * `reason` is one of: * - `http_401` — session token invalid / expired (auth-service rejected) * - `http_4xx` / `http_5xx` — generic upstream error * - `network` — fetch to iframe's own backend failed * - `mismatch` — session token's user didn't match `accountUuid` */ interface AddAccountWithTokenFailedPayload { reason: string; message?: string; } /** * Prep–Sign–Promote (v1.4) — iframe → host: signature captured. * Fires from the peer's /sharing/embed/{slug}/{prep_id} surface after a * successful POST to .../submit. The orchestrator's listens * for this to chain into Sharing::shareUser + Sharing::promote. */ interface PrepSignedPayload { prep_id: string; } /** * Prep–Sign–Promote (v1.4) — iframe → host: signature rejected. * `error` mirrors the JSON body's `error` field from /submit (e.g. * `handler_rejected`, `invalid_state`, `not_found`). */ interface PrepSignFailedPayload { prep_id: string; error: string; message?: string; } /** * PostMessage client for communicating with the auth service iframe */ declare class PostMessageClient { private iframe; private iframeOrigin; private isConnected; private eventHandlers; private pendingRequests; private debug; private serviceApiKey; constructor(config: AccountSwitcherConfig); /** * Set the iframe reference */ setIframe(iframe: HTMLIFrameElement, origin: string): void; /** * Handle incoming PostMessage events */ private handleMessage; /** * Handle READY message from iframe */ private handleReady; /** * Register an event handler */ on(eventType: string, handler: Function): void; /** * Unregister an event handler */ off(eventType: string, handler: Function): void; /** * Emit an event to all registered handlers */ private emit; /** * Send a message to the iframe */ private sendMessage; /** * Send a request and wait for response */ private request; /** * Switch to a different account */ switchAccount(userUuid: string): Promise; /** * Add a new account */ addAccount(): Promise; /** * Manage account (navigate to account management page) */ manageAccount(): Promise; /** * Update avatar (navigate to avatar update page) */ updateAvatar(): Promise; /** * Logout a specific account */ logoutAccount(userUuid: string): Promise; /** * Logout all accounts */ logoutAll(): Promise; /** * Get current session state */ getSession(): Promise; /** * Set session from external login (e.g., host application's login flow) */ setSession(sessionData: SetSessionPayload): Promise; /** * Send dialog response */ sendDialogResponse(type: string, requestId: string, payload: any): void; /** * Public: post a fully-enveloped, fire-and-forget message at the iframe. * * Unlike `request()`, this does not await a response. A requestId, timestamp * and protocol version are attached automatically so the auth-service iframe's * isValidMessage() accepts the message. Used by the cross-product handoff * (sharing/multiAccountAutoAdd) via the provider context's `sendMessage`. */ send(type: string, payload?: any): void; /** * Public: whether the client can actually deliver a message to the iframe — * i.e. an iframe is registered AND the handshake has completed. The iframe's * bridge drops any non-HANDSHAKE message received before its own handshake, * so callers that fire one-shot messages (e.g. the handoff auto-add) should * wait for this before sending. */ isReady(): boolean; /** * Clean up resources */ destroy(): void; } /** * User data structure from auth service */ interface User { uuid: string; name: string; email: string; avatar?: string; created_at?: string; } /** * Session state containing authentication status and user data */ interface Session { isAuthenticated: boolean; currentUser: User | null; accounts: User[]; } /** * Dialog configuration for interactive prompts */ interface DialogConfig { enabled?: boolean; closeOnOverlayClick?: boolean; closeOnEscape?: boolean; } /** * Configuration for the AccountSwitcher provider */ interface AccountSwitcherConfig { /** Backend API URL (e.g., Laravel backend) */ backendUrl: string; /** Auth service URL (optional, for iframe origin) */ authServiceUrl?: string; /** Service API key for handshake authentication */ serviceApiKey?: string; /** Callback when session changes */ onSessionChange?: (session: Session) => void; /** Callback when account is switched */ onAccountChange?: (user: User) => void; /** Callback when error occurs */ onError?: (error: Error) => void; /** Enable debug logging */ debug?: boolean; /** Dialog configuration */ dialogs?: DialogConfig; /** Custom confirm handler */ onConfirmRequest?: (payload: ConfirmPayload) => Promise; /** Custom prompt handler */ onPromptRequest?: (payload: PromptPayload) => Promise; /** Custom alert handler */ onAlertRequest?: (payload: AlertPayload) => Promise; /** Enable auto-resize */ autoResize?: boolean; /** Minimum iframe height (pixels) */ minHeight?: number; /** Maximum iframe height (pixels) */ maxHeight?: number | null; /** Callback when iframe is resized */ onResize?: (height: number) => void; /** * Unified navigation handler (Unified Action Protocol) * Handles all URL redirects with reason and tab preference */ onNavigate?: (payload: UrlRedirectPayload) => void; /** * Custom handler for add account navigation * @deprecated Use onNavigate instead for better extensibility */ onNavigateToAddAccount?: (url: string) => void; /** * Custom handler for account management navigation * @deprecated Use onNavigate instead for better extensibility */ onNavigateToManageAccount?: (url: string) => void; /** * Custom handler for avatar update navigation * @deprecated Use onNavigate instead for better extensibility */ onNavigateToAvatarUpdate?: (url: string) => void; } /** * Context value provided by AccountSwitcherProvider */ interface AccountSwitcherContextValue { session: Session; isLoading: boolean; error: Error | null; switchAccount: (userUuid: string) => Promise; addAccount: () => Promise; manageAccount: () => Promise; updateAvatar: () => Promise; logoutAccount: (userUuid: string) => Promise; logoutAll: () => Promise; refresh: () => Promise; registerIframe: (iframe: HTMLIFrameElement, origin: string) => void; /** * The live PostMessage client, or `null` until the provider's mount effect * has initialized it. Consumers that talk to the iframe directly — e.g. the * cross-product handoff — must wait for this to become non-null. Exposed for * `sharing/multiAccountAutoAdd`. */ client: PostMessageClient | null; /** * Fire a fully-enveloped, fire-and-forget message at the auth-service iframe * (auto-attaches requestId/timestamp/version). No-ops until the client + * iframe are ready. Exposed for the handoff flow. */ sendMessage: (type: string, payload?: unknown) => void; } /** * Payload for confirm dialog */ interface ConfirmPayload { title?: string; message: string; confirmText?: string; cancelText?: string; variant?: 'info' | 'warning' | 'danger' | 'error' | 'success'; } /** * Payload for prompt dialog */ interface PromptPayload { title?: string; message: string; defaultValue?: string; placeholder?: string; variant?: 'info' | 'warning' | 'danger' | 'error' | 'success'; } /** * Payload for alert dialog */ interface AlertPayload { title?: string; message: string; variant?: 'info' | 'warning' | 'danger' | 'error' | 'success'; } /** * PostMessage event types */ type PostMessageEventType = 'SESSION_CHANGED' | 'ACCOUNT_SWITCHED' | 'ERROR' | 'READY' | 'HANDSHAKE_ACK' | 'RESIZE'; /** * PostMessage event handler */ type PostMessageEventHandler = (payload: T) => void; /** * Payload for setting session data from external login */ interface SetSessionPayload { isAuthenticated: boolean; currentUser: { uuid: string; name: string; email: string; avatar?: string; roles?: string[]; auth_token?: string; }; accounts: Array<{ uuid: string; name: string; email: string; avatar?: string; is_active: boolean; is_primary: boolean; roles?: string[]; }>; token: string; session_id: string; } export { type AccountSwitcherConfig as A, type ConfirmPayload as C, type DialogConfig as D, type ErrorPayload as E, MESSAGE_TYPES as M, PostMessageClient as P, type ResizePayload as R, type Session as S, type User as U, type AccountSwitcherContextValue as a, type PromptPayload as b, type AlertPayload as c, type PostMessageEventType as d, type PostMessageEventHandler as e, type SetSessionPayload as f, type UrlRedirectPayload as g, type PostMessageData as h, type SessionChangedPayload as i, type AccountSwitchedPayload as j, type ActionRequestPayload as k, type AddAccountWithTokenPayload as l, type AddAccountWithTokenOkPayload as m, type AddAccountWithTokenFailedPayload as n, type PrepSignedPayload as o, type PrepSignFailedPayload as p };