@mosano-product-framework/sdk 0.2.0 → 0.2.2

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/identity/index.ts","../src/identity/v0.ts","../src/identity/types.ts"],"names":[],"mappings":"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","file":"chunk-XAXFIIRT.js","sourcesContent":["import type { ClientConfig, TokenProvider } from '../client/core/types.js';\nimport { attachStandardMiddlewares } from '../client/core/client-factory.js';\nimport { createTurnstileMiddleware } from '../client/middlewares/turnstile.js';\nimport {\n createAdminAuthMiddleware,\n type AdminAuthMiddlewareOptions,\n} from '../client/middlewares/admin-auth.js';\nimport type { TenantSelectionStore } from '../auth/tenant-selection.js';\nimport type { OAuthStateStore } from '../auth/oauth-state.js';\nimport { AuthClientV0 } from './v0.js';\n\n/**\n * Provider for minting single-use Cloudflare Turnstile tokens.\n */\nexport interface TurnstileProvider {\n /** Mint a fresh single-use Turnstile token. */\n getToken: () => Promise<string>;\n}\n\n/**\n * Configuration options for the Auth client\n */\nexport interface AuthClientOptions extends Omit<ClientConfig, 'baseUrl'> {\n /**\n * Base URL for the Auth service\n */\n baseUrl: string;\n /** Optional token provider. Auto-wires auth middleware when provided. */\n tokenProvider?: TokenProvider;\n /** Optional Turnstile token provider for bot protection. */\n turnstileProvider?: TurnstileProvider;\n /**\n * Optional shared tenant selection. When provided, every request carries the\n * selected tenant headers. Construct it with `createTenantSelection()` and\n * share the same instance across identity/storage/graphql clients.\n */\n tenantProvider?: TenantSelectionStore;\n /**\n * Optional store for the OAuth CSRF state. When provided,\n * `getGoogleOAuthURL` persists the minted state so it survives the redirect.\n * Build one with `createOAuthStateStore()`.\n */\n oauthStateStore?: OAuthStateStore;\n}\n\n/**\n * Creates an Auth client for API v0\n *\n * @param options - Client configuration options\n * @returns AuthClientV0 instance\n *\n * @example\n * ```typescript\n * import { createAuthClient } from '@mosano-product-framework/sdk/identity';\n *\n * // Create client without authentication (for public endpoints)\n * const auth = createAuthClient({\n * baseUrl: 'https://api.example.com/auth',\n * });\n *\n * // Register a new user\n * const { access_token, refresh_token } = await auth.signUpEmailPassword({\n * name: 'John Doe',\n * email: 'john@example.com',\n * password: 'securePassword123',\n * });\n *\n * // Create authenticated client with token provider\n * const authenticatedAuth = createAuthClient({\n * baseUrl: 'https://api.example.com/auth',\n * tokenProvider: {\n * getAccessToken: () => localStorage.getItem('accessToken'),\n * onTokenExpired: () => { window.location.href = '/login'; },\n * },\n * });\n *\n * // Get user profile\n * const profile = await authenticatedAuth.getMe();\n * ```\n */\n/**\n * SDK endpoint paths that require a Turnstile token.\n * Must match the go-identity routes with turnstile.Verify() middleware.\n */\nconst TURNSTILE_PROTECTED_PATHS = [\n '/sign-up-email-password',\n '/sign-in-email-password',\n '/forgot-password-with-email',\n '/password/recovery/verify',\n '/password/reset',\n '/passkey/login/begin',\n '/passkey/login/finish',\n '/oauth/google/callback',\n '/accept', // matches /invitations/{token}/accept\n '/invite', // matches /tenants/{id}/members/invite\n];\n\nexport function createAuthClient(options: AuthClientOptions): AuthClientV0 {\n const { tokenProvider, turnstileProvider, tenantProvider, ...clientConfig } = options;\n const client = new AuthClientV0(clientConfig);\n\n attachStandardMiddlewares(client, { tokenProvider, tenantProvider });\n\n if (turnstileProvider) {\n client.use(createTurnstileMiddleware({\n getToken: turnstileProvider.getToken,\n protectedPaths: TURNSTILE_PROTECTED_PATHS,\n }));\n }\n\n return client;\n}\n\n/**\n * Configuration options for an admin-authenticated Auth client.\n *\n * SECURITY: Admin authentication uses the shared `ADMIN_JWT_SECRET`, which can\n * impersonate any user. Only construct an admin client server-side / in trusted\n * services. NEVER ship the secret to a browser.\n */\nexport interface AdminClientOptions extends Omit<ClientConfig, 'baseUrl'> {\n /** Base URL for the Auth service. */\n baseUrl: string;\n /** Admin auth options: either a pre-minted `token` or a minting `config`. */\n admin: AdminAuthMiddlewareOptions;\n}\n\n/**\n * Creates an admin-authenticated Auth client for API v0.\n *\n * The returned client sends `Authorization: Admin <jwt>` on every request,\n * acting on behalf of the configured principal. Mirrors {@link createAuthClient}\n * but wires the admin auth middleware instead of the Bearer one.\n *\n * SECURITY: Requires the shared `ADMIN_JWT_SECRET` (when using a minting\n * `config`). Server-side / trusted-service use ONLY — never expose the secret\n * to a browser.\n *\n * @param options - Client configuration options.\n * @returns AuthClientV0 instance authenticated as an admin.\n *\n * @example\n * ```typescript\n * import { createAdminClient } from '@mosano-product-framework/sdk/identity';\n *\n * // Mint a fresh admin token per request (server-side only).\n * const admin = createAdminClient({\n * baseUrl: 'https://api.example.com/auth',\n * admin: {\n * config: {\n * secret: process.env.ADMIN_JWT_SECRET!,\n * actOnBehalfOf: { userId, onTenantId: tenantId },\n * ttlSeconds: 60,\n * },\n * },\n * });\n * ```\n */\nexport function createAdminClient(options: AdminClientOptions): AuthClientV0 {\n const { admin, ...clientConfig } = options;\n const client = new AuthClientV0(clientConfig);\n client.use(createAdminAuthMiddleware(admin));\n return client;\n}\n\nexport { AuthClientV0, type AuthClientV0Config } from './v0.js';\nexport * from './types.js';\n","import { MPFClient } from '../client/core/client.js';\nimport type { ClientConfig, RequestOptions } from '../client/core/types.js';\nimport { MPFValidationError } from '../client/core/errors.js';\nimport type { OAuthStateStore } from '../auth/oauth-state.js';\nimport type * as Types from './types.js';\n\n/**\n * Configuration for the identity client.\n */\nexport interface AuthClientV0Config extends ClientConfig {\n /**\n * Optional store for the OAuth CSRF state. When provided,\n * `getGoogleOAuthURL` persists the minted state automatically so it survives\n * the redirect.\n *\n * Sending it back stays explicit — `GoogleOAuthCallbackRequest.state` is\n * required — because a security parameter should not be injected invisibly.\n */\n oauthStateStore?: OAuthStateStore;\n}\n\n/**\n * Auth API v0 client\n *\n * Provides methods for authentication, user management, sessions,\n * password recovery, and multi-tenant operations.\n */\nexport class AuthClientV0 extends MPFClient {\n /** Optional OAuth state store; see {@link AuthClientV0Config.oauthStateStore}. */\n private readonly oauthStateStore?: OAuthStateStore;\n\n constructor(config: AuthClientV0Config) {\n const { oauthStateStore, ...clientConfig } = config;\n super({\n ...clientConfig,\n baseUrl: `${clientConfig.baseUrl}/v0`,\n });\n this.oauthStateStore = oauthStateStore;\n }\n\n /**\n * Wraps request options with skipAuth: true for public endpoints\n * that do not require authentication headers.\n */\n private publicOptions(options?: RequestOptions): RequestOptions {\n return { ...options, skipAuth: true };\n }\n\n // ============================================================================\n // Public Endpoints - Authentication\n // ============================================================================\n\n /**\n * Register a new user with email and password\n *\n * Creates a new user account and returns access and refresh tokens.\n *\n * @param data - User registration data\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async signUpEmailPassword(\n data: Types.CreateUserRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n const cleanedData = {\n email: data.email,\n password: data.password,\n ...(data.first_name ? { first_name: data.first_name } : {}),\n ...(data.last_name ? { last_name: data.last_name } : {}),\n ...(data.display_name ? { display_name: data.display_name } : {}),\n };\n return this.post<Types.AccessDataResponse>(\n '/sign-up-email-password',\n cleanedData,\n this.publicOptions(options)\n );\n }\n\n /**\n * Login with email and password\n *\n * Authenticates a user and returns access and refresh tokens.\n *\n * @param data - Login credentials\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async signInEmailPassword(\n data: Types.LoginRequest,\n options?: RequestOptions\n ): Promise<Types.LoginResponse> {\n return this.post<Types.LoginResponse>(\n '/sign-in-email-password',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Verify MFA code to complete login\n *\n * After a login attempt returns mfa_required, submit the TOTP code\n * along with the MFA ticket to complete authentication.\n *\n * @param data - MFA ticket and TOTP code\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async verifyMFA(\n data: Types.MFAVerifyRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/mfa/verify',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Verify MFA setup to complete first-time enrollment and login\n *\n * After a login attempt returns mfa_setup_required, verify the TOTP\n * setup by submitting a code from the authenticator app.\n *\n * @param data - MFA ticket and verification code\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async verifyMFASetup(\n data: Types.MFASetupVerifyRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/mfa/setup/verify',\n data,\n this.publicOptions(options)\n );\n }\n\n // ============================================================================\n // Public Endpoints - Password Recovery\n // ============================================================================\n\n /**\n * Send password recovery code to email\n *\n * Initiates the password recovery process by sending a verification code.\n *\n * @param data - Email address for recovery\n * @param options - Optional request options\n * @returns Success response\n */\n async forgotPasswordWithEmail(\n data: Types.SendRecoveryCodeRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n '/forgot-password-with-email',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Verify password recovery code\n *\n * Verifies the recovery code and returns a recovery token for password reset.\n *\n * @param data - Email and verification code\n * @param options - Optional request options\n * @returns Recovery token for password reset\n */\n async verifyRecoveryCode(\n data: Types.VerifyRecoveryCodeRequest,\n options?: RequestOptions\n ): Promise<Types.RecoveryTokenResponse> {\n return this.post<Types.RecoveryTokenResponse>(\n '/password/recovery/verify',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Reset password with recovery token\n *\n * Resets the user's password and returns new access and refresh tokens.\n *\n * @param data - Recovery token and new password\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async resetPassword(\n data: Types.ResetPasswordRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/password/reset',\n data,\n this.publicOptions(options)\n );\n }\n\n // ============================================================================\n // Public Endpoints - Sessions\n // ============================================================================\n\n /**\n * Renew session with refresh token\n *\n * Exchanges a valid refresh token for new access and refresh tokens.\n *\n * Tenant is selected per request via the `X-MPF-Tenant` header, so a renewal\n * neither takes nor changes a tenant.\n *\n * @param data - Refresh token\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async renewSession(\n data: Types.RenewSessionRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/sessions/renew',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Revoke session (logout)\n *\n * Revokes the session associated with the provided refresh token.\n * Requires authentication.\n *\n * @param data - Refresh token to revoke\n * @param options - Optional request options\n * @returns Success response\n */\n async revokeSession(\n data: Types.RevokeSessionRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n '/sessions/revoke',\n data,\n options\n );\n }\n\n // ============================================================================\n // Public Endpoints - Invitations\n // ============================================================================\n\n /**\n * List pending invitations for the authenticated user\n *\n * Returns all pending invitations for the currently authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of pending invitations\n */\n async listMyInvitations(\n options?: RequestOptions\n ): Promise<Types.PendingInvitationResponse[]> {\n return this.get<Types.PendingInvitationResponse[]>(\n '/users/me/invitations',\n options\n );\n }\n\n /**\n * Preview an invitation (public, pre-auth).\n *\n * Returns the tenant, role, and inviter display name for the\n * invitation-acceptance page. Email is intentionally omitted. Use this\n * to render the accept page before the user signs in.\n *\n * @param token - Invitation token\n * @param options - Optional request options\n * @returns Public-safe invitation preview\n */\n async previewInvitation(\n token: string,\n options?: RequestOptions\n ): Promise<Types.InvitationPreviewResponse> {\n return this.get<Types.InvitationPreviewResponse>(\n `/invitations/${encodeURIComponent(token)}`,\n this.publicOptions(options)\n );\n }\n\n /**\n * Accept an invitation.\n *\n * Requires the user to be authenticated. The user's primary verified\n * email must match the invitation. Creates the membership row.\n *\n * @param token - Invitation token\n * @param options - Optional request options\n * @returns Acceptance result (invitation + new membership)\n */\n async acceptInvitation(\n token: string,\n options?: RequestOptions\n ): Promise<Types.AcceptInvitationResponse> {\n return this.post<Types.AcceptInvitationResponse>(\n `/invitations/${encodeURIComponent(token)}/accept`,\n undefined,\n options\n );\n }\n\n /**\n * Revoke a pending invitation. Caller must be a manager of the tenant\n * that issued the invitation.\n *\n * @param invitationId - Invitation ID (not the token)\n * @param options - Optional request options\n */\n async revokeInvitation(\n invitationId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/invitations/${encodeURIComponent(invitationId)}`,\n options\n );\n }\n\n // ============================================================================\n // Public Endpoints - Health\n // ============================================================================\n\n /**\n * Health check endpoint\n *\n * Returns the health status of the service.\n *\n * @param options - Optional request options\n * @returns Health status\n */\n async healthCheck(options?: RequestOptions): Promise<Types.HealthResponse> {\n return this.get<Types.HealthResponse>('/healthz', this.publicOptions(options));\n }\n\n // ============================================================================\n // Protected Endpoints - User Profile\n // ============================================================================\n\n /**\n * Get current user profile\n *\n * Returns the authenticated user's profile information.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns User profile\n */\n async getMe(options?: RequestOptions): Promise<Types.UserProfileResponse> {\n return this.get<Types.UserProfileResponse>('/users/me', options);\n }\n\n /**\n * Update current user profile\n *\n * Updates the authenticated user's profile information.\n * Requires authentication.\n *\n * @param data - Profile update data\n * @param options - Optional request options\n * @returns Updated user profile\n */\n async updateMe(\n data: Types.UpdateProfileRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.patch<Types.SuccessResponse>('/users/me', data, options);\n }\n\n // ============================================================================\n // Protected Endpoints - Emails\n // ============================================================================\n\n /**\n * List user emails\n *\n * Returns all email addresses associated with the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of email addresses\n */\n async listEmails(options?: RequestOptions): Promise<Types.EmailResponse[]> {\n const response = await this.get<Types.EmailsResponse>('/users/me/emails', options);\n return response.emails;\n }\n\n /**\n * Add a new email address\n *\n * Adds a new email address to the authenticated user's account.\n * A verification code will be sent to the email.\n * Requires authentication.\n *\n * @param data - Email address to add\n * @param options - Optional request options\n * @returns Added email information\n */\n async addEmail(\n data: Types.AddEmailRequest,\n options?: RequestOptions\n ): Promise<Types.EmailResponse> {\n return this.post<Types.EmailResponse>('/users/me/emails', data, options);\n }\n\n /**\n * Verify an email address\n *\n * Verifies an email address using a verification code.\n * Requires authentication.\n *\n * @param emailId - Email ID to verify\n * @param data - Verification code\n * @param options - Optional request options\n * @returns Success response\n */\n async verifyEmail(\n emailId: string,\n data: Types.VerifyContactRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n `/users/me/emails/${encodeURIComponent(emailId)}/verify`,\n data,\n options\n );\n }\n\n /**\n * Delete an email address\n *\n * Removes an email address from the authenticated user's account.\n * Cannot delete the primary email.\n * Requires authentication.\n *\n * @param emailId - Email ID to delete\n * @param options - Optional request options\n * @returns Success response\n */\n async deleteEmail(\n emailId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/users/me/emails/${encodeURIComponent(emailId)}`,\n undefined,\n options\n );\n }\n\n /**\n * Set email as primary\n *\n * Sets the specified email address as the primary email for the user.\n * Email must be verified before it can be set as primary.\n * Requires authentication.\n *\n * @param emailId - Email ID to set as primary\n * @param options - Optional request options\n * @returns Success response\n */\n async setPrimaryEmail(\n emailId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n `/users/me/emails/${encodeURIComponent(emailId)}/set-primary`,\n undefined,\n options\n );\n }\n\n /**\n * Send email verification code\n *\n * Sends a verification code to the authenticated user's primary email address.\n * Use verifyEmail() to complete the verification.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Success response\n */\n async sendEmailVerification(\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n '/email/send-verification',\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Phones\n // ============================================================================\n\n /**\n * List user phones\n *\n * Returns all phone numbers associated with the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of phone numbers\n */\n async listPhones(options?: RequestOptions): Promise<Types.PhoneResponse[]> {\n const response = await this.get<Types.PhonesResponse>('/users/me/phones', options);\n return response.phones;\n }\n\n /**\n * Add a new phone number\n *\n * Adds a new phone number to the authenticated user's account.\n * A verification code will be sent to the phone.\n * Requires authentication.\n *\n * @param data - Phone number to add (E.164 format)\n * @param options - Optional request options\n * @returns Added phone information\n */\n async addPhone(\n data: Types.AddPhoneRequest,\n options?: RequestOptions\n ): Promise<Types.PhoneResponse> {\n return this.post<Types.PhoneResponse>('/users/me/phones', data, options);\n }\n\n /**\n * Verify a phone number\n *\n * Verifies a phone number using a verification code.\n * Requires authentication.\n *\n * @param phoneId - Phone ID to verify\n * @param data - Verification code\n * @param options - Optional request options\n * @returns Success response\n */\n async verifyPhone(\n phoneId: string,\n data: Types.VerifyContactRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n `/users/me/phones/${encodeURIComponent(phoneId)}/verify`,\n data,\n options\n );\n }\n\n /**\n * Delete a phone number\n *\n * Removes a phone number from the authenticated user's account.\n * Cannot delete the primary phone.\n * Requires authentication.\n *\n * @param phoneId - Phone ID to delete\n * @param options - Optional request options\n * @returns Success response\n */\n async deletePhone(\n phoneId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/users/me/phones/${encodeURIComponent(phoneId)}`,\n undefined,\n options\n );\n }\n\n /**\n * Set phone as primary\n *\n * Sets the specified phone number as the primary phone for the user.\n * Phone must be verified before it can be set as primary.\n * Requires authentication.\n *\n * @param phoneId - Phone ID to set as primary\n * @param options - Optional request options\n * @returns Success response\n */\n async setPrimaryPhone(\n phoneId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n `/users/me/phones/${encodeURIComponent(phoneId)}/set-primary`,\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Sessions\n // ============================================================================\n\n /**\n * List user sessions\n *\n * Returns all active sessions for the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of sessions\n */\n async listSessions(\n options?: RequestOptions\n ): Promise<Types.SessionResponse[]> {\n const response = await this.get<Types.SessionsResponse>('/users/me/sessions', options);\n return response.sessions;\n }\n\n /**\n * Delete a session\n *\n * Revokes a specific session for the authenticated user.\n * Requires authentication.\n *\n * @param sessionId - Session ID to delete\n * @param options - Optional request options\n * @returns Success response\n */\n async deleteSession(\n sessionId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/users/me/sessions/${encodeURIComponent(sessionId)}`,\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Clients\n // ============================================================================\n\n /**\n * List authorized OAuth clients\n *\n * Returns all OAuth clients authorized by the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of OAuth clients\n */\n async listClients(options?: RequestOptions): Promise<Types.ClientResponse[]> {\n const response = await this.get<Types.ClientsResponse>('/users/me/clients', options);\n return response.clients;\n }\n\n /**\n * Revoke OAuth client authorization\n *\n * Revokes authorization for a specific OAuth client.\n * Requires authentication.\n *\n * @param clientId - Client ID to revoke\n * @param options - Optional request options\n * @returns Success response\n */\n async deleteClient(\n clientId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/users/me/clients/${encodeURIComponent(clientId)}`,\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Password\n // ============================================================================\n\n /**\n * Update password (authenticated)\n *\n * Updates the authenticated user's password.\n * Requires authentication.\n *\n * @param data - Current and new password\n * @param options - Optional request options\n * @returns Success response\n */\n async updatePassword(\n data: Types.UpdatePasswordRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n '/password/update',\n data,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Tenants\n // ============================================================================\n\n /**\n * Create a new tenant\n *\n * Creates a new tenant organization. The authenticated user becomes the owner.\n * Requires authentication.\n *\n * @param data - Tenant creation data\n * @param options - Optional request options\n * @returns Created tenant information\n */\n async createTenant(\n data: Types.CreateTenantRequest,\n options?: RequestOptions\n ): Promise<Types.TenantResponse> {\n return this.post<Types.TenantResponse>('/tenants', data, options);\n }\n\n /**\n * List current user's tenants\n *\n * Returns all tenants the authenticated user is a member of.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of tenant information\n */\n async listMyTenants(\n options?: RequestOptions\n ): Promise<Types.TenantResponse[]> {\n return this.get<Types.TenantResponse[]>('/users/me/tenants', options);\n }\n\n // ============================================================================\n // Protected Endpoints - Tenant Members\n // ============================================================================\n\n /**\n * List tenant members\n *\n * Returns all members of the specified tenant.\n * Requires authentication and membership in the tenant.\n *\n * @param tenantId - Tenant ID\n * @param options - Optional request options\n * @returns Array of tenant members\n */\n async listTenantMembers(\n tenantId: string,\n options?: RequestOptions\n ): Promise<Types.MembershipResponse[]> {\n const response = await this.get<Types.MembersResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/members`,\n options\n );\n return response.members;\n }\n\n /**\n * Invite a member to tenant\n *\n * Sends an invitation to join the tenant. Requires authentication and\n * owner/admin role on the tenant.\n *\n * @param tenantId - Target tenant ID\n * @param data - Invitation data\n * @param options - Optional request options\n * @returns Invitation result, including a copyable accept_url\n */\n async inviteTenantMember(\n tenantId: string,\n data: Types.InviteMemberRequest,\n options?: RequestOptions\n ): Promise<Types.InvitationResponse> {\n return this.post<Types.InvitationResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/members/invite`,\n data,\n options\n );\n }\n\n /**\n * List pending invitations issued by the authenticated caller for a tenant.\n *\n * Returns only invitations whose `invited_by` matches the caller. Lets the\n * caller copy the `accept_url` of an invite they previously sent (for\n * example, to re-share if email delivery failed). Callers without a\n * membership, and members who never issued an invite for this tenant,\n * get an empty array.\n *\n * @param tenantId - Tenant ID\n * @param options - Optional request options\n * @returns Array of invitations issued by the caller\n */\n async listTenantInvitationsIssuedByMe(\n tenantId: string,\n options?: RequestOptions\n ): Promise<Types.IssuedInvitationResponse[]> {\n const response = await this.get<Types.IssuedInvitationsResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/invitations`,\n options\n );\n return response.invitations;\n }\n\n /**\n * Update member role\n *\n * Updates the role of a tenant member.\n * Requires authentication and owner role in the tenant.\n *\n * @param tenantId - Tenant ID\n * @param userId - User ID of the member\n * @param data - New role\n * @param options - Optional request options\n * @returns Updated membership information\n */\n async updateTenantMemberRole(\n tenantId: string,\n userId: string,\n data: Types.UpdateMemberRoleRequest,\n options?: RequestOptions\n ): Promise<Types.MembershipResponse> {\n return this.patch<Types.MembershipResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(userId)}`,\n data,\n options\n );\n }\n\n /**\n * Remove member from tenant\n *\n * Removes a member from the tenant.\n * Cannot remove the last owner.\n * Requires authentication and admin/owner role in the tenant.\n *\n * @param tenantId - Tenant ID\n * @param userId - User ID of the member to remove\n * @param options - Optional request options\n * @returns Success response\n */\n async removeTenantMember(\n tenantId: string,\n userId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(userId)}`,\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - TOTP (Two-Factor Authentication)\n // ============================================================================\n\n /**\n * Setup TOTP two-factor authentication\n *\n * Initializes TOTP setup and returns the secret, QR code URL, and backup codes.\n * The setup must be verified with verifyTOTP() before it becomes active.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns TOTP setup data including secret and backup codes\n */\n async setupTOTP(\n options?: RequestOptions\n ): Promise<Types.TOTPSetupResponse> {\n return this.post<Types.TOTPSetupResponse>(\n '/totp/setup',\n undefined,\n options\n );\n }\n\n /**\n * Verify TOTP setup\n *\n * Verifies a TOTP code to complete the 2FA setup process.\n * After verification, TOTP will be required on future logins.\n * Requires authentication.\n *\n * @param data - TOTP verification code\n * @param options - Optional request options\n * @returns Success response\n */\n async verifyTOTP(\n data: Types.VerifyTOTPRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>('/totp/verify', data, options);\n }\n\n /**\n * Disable TOTP two-factor authentication\n *\n * Disables TOTP 2FA. Requires a valid TOTP code to confirm.\n * Requires authentication.\n *\n * @param data - TOTP code to confirm disable\n * @param options - Optional request options\n * @returns Success response\n */\n async disableTOTP(\n data: Types.DisableTOTPRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>('/totp/disable', data, options);\n }\n\n // ============================================================================\n // Passkey / WebAuthn - Public Endpoints\n // ============================================================================\n\n /**\n * Begin passkey login\n *\n * Starts the WebAuthn authentication process.\n * Returns options to pass to navigator.credentials.get().\n *\n * @param options - Optional request options\n * @returns WebAuthn request options\n */\n async beginPasskeyLogin(\n options?: RequestOptions\n ): Promise<Types.BeginPasskeyLoginResponse> {\n const response = await this.post<Types.BeginPasskeyLoginResponse & { session_key?: string }>(\n '/passkey/login/begin',\n undefined,\n this.publicOptions(options)\n );\n // Handle both shapes: server may return { publicKey: {...} } or flat { challenge, ... }\n const raw = response.options as unknown as Record<string, unknown>;\n const opts = ('publicKey' in raw ? raw.publicKey : raw) as Types.WebAuthnRequestOptions;\n return { options: opts, session_key: response.session_key ?? '' };\n }\n\n /**\n * Complete passkey login\n *\n * Completes the WebAuthn authentication and returns access tokens.\n *\n * @param data - WebAuthn assertion result from navigator.credentials.get()\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async finishPasskeyLogin(\n data: Types.FinishPasskeyLoginRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/passkey/login/finish',\n data,\n this.publicOptions(options)\n );\n }\n\n // ============================================================================\n // Passkey / WebAuthn - Protected Endpoints\n // ============================================================================\n\n /**\n * Begin passkey registration\n *\n * Starts the WebAuthn registration process for the authenticated user.\n * Returns options to pass to navigator.credentials.create().\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns WebAuthn creation options\n */\n async beginPasskeyRegistration(\n options?: RequestOptions\n ): Promise<Types.BeginPasskeyRegistrationResponse> {\n const response = await this.post<Types.BeginPasskeyRegistrationResponse>(\n '/passkeys/register/begin',\n undefined,\n options\n );\n // Handle both shapes: server may return { publicKey: {...} } or flat { rp, user, ... }\n const raw = response.options as unknown as Record<string, unknown>;\n const opts = ('publicKey' in raw ? raw.publicKey : raw) as Types.WebAuthnCreationOptions;\n return { options: opts };\n }\n\n /**\n * Complete passkey registration\n *\n * Completes the WebAuthn registration with the attestation result.\n * Requires authentication.\n *\n * @param data - WebAuthn attestation result and optional passkey name\n * @param options - Optional request options\n * @returns Success response\n */\n async finishPasskeyRegistration(\n data: Types.FinishPasskeyRegistrationRequest,\n options?: RequestOptions\n ): Promise<Types.PasskeyResponse> {\n return this.post<Types.PasskeyResponse>(\n '/passkeys/register/finish',\n data,\n options\n );\n }\n\n /**\n * List registered passkeys\n *\n * Returns all passkeys registered by the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of passkey information\n */\n async listPasskeys(\n options?: RequestOptions\n ): Promise<Types.PasskeyResponse[]> {\n const response = await this.get<Types.PasskeysResponse>('/passkeys', options);\n return response.passkeys;\n }\n\n /**\n * Delete a passkey\n *\n * Removes a registered passkey from the authenticated user's account.\n * If the user has TOTP 2FA enabled, a valid TOTP code must be provided.\n * Requires authentication.\n *\n * @param passkeyId - Passkey ID to delete\n * @param data - Optional request body with TOTP code for 2FA verification\n * @param options - Optional request options\n * @returns Success response\n */\n async deletePasskey(\n passkeyId: string,\n data?: Types.DeletePasskeyRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/passkeys/${encodeURIComponent(passkeyId)}`,\n data,\n options\n );\n }\n\n // ============================================================================\n // Google OAuth - Public Endpoints\n // ============================================================================\n\n /**\n * Get Google OAuth authorization URL and its CSRF state.\n *\n * Returns `{ url, state }`. Redirect the user to `url`, and keep `state` —\n * `handleGoogleOAuthCallback` requires it. When the client was constructed\n * with an `oauthStateStore`, the state is persisted here automatically.\n *\n * @param params - Query parameters including redirect_uri\n * @param options - Optional request options\n * @returns The authorization URL and the single-use state to round-trip\n */\n async getGoogleOAuthURL(\n params: { redirect_uri: string },\n options?: RequestOptions\n ): Promise<Types.GoogleOAuthURLResponse> {\n const queryParams = new URLSearchParams({ redirect_uri: params.redirect_uri });\n const response = await this.get<Types.GoogleOAuthURLResponse>(\n `/oauth/google/url?${queryParams.toString()}`,\n this.publicOptions(options)\n );\n\n // Persist before the caller redirects. Done here rather than left to the\n // caller because \"remember to store this across a full-page redirect\" is\n // exactly the step whose omission made this flow exploitable.\n if (this.oauthStateStore && response.state) {\n this.oauthStateStore.save(response.state);\n }\n\n return response;\n }\n\n /**\n * Handle Google OAuth callback\n *\n * Exchanges the Google OAuth authorization code for access tokens.\n * Creates a new user if one doesn't exist with the Google email.\n *\n * The `state` from `getGoogleOAuthURL` is **required**: the server validates\n * it before exchanging the code, and rejects a mismatch, absence, expiry or\n * reuse. See {@link Types.GoogleOAuthCallbackRequest.state}.\n *\n * @param data - OAuth callback data: code, redirect_uri and state\n * @param options - Optional request options\n * @returns Access and refresh tokens\n * @throws {MPFValidationError} If `state` is missing or empty (client-side).\n */\n async handleGoogleOAuthCallback(\n data: Types.GoogleOAuthCallbackRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n // Fail here rather than sending a request the server must reject. A caller\n // reaching this with no state has lost the pending flow (wrong tab, cleared\n // storage, or a hand-rolled callback that dropped it) and the local error\n // names the cause; a server-side rejection would not.\n if (typeof data.state !== 'string' || data.state === '') {\n throw new MPFValidationError(\n 'OAuth callback requires the `state` returned by getGoogleOAuthURL. ' +\n 'It is the CSRF defence for this flow: without it a callback carrying ' +\n \"an attacker's authorization code would be accepted. Persist it across \" +\n 'the redirect with createOAuthStateStore().',\n { field: 'state' },\n { state: ['state is required'] }\n );\n }\n\n return this.post<Types.AccessDataResponse>(\n '/oauth/google/callback',\n data,\n this.publicOptions(options)\n );\n }\n}\n","import type { MPFRole } from '../auth/claims-types.js';\n\n// NOTE: deliberately NOT re-exported (`export type { MPFRole }`).\n//\n// This module is namespace-re-exported from the root barrel as `AuthTypes`, and\n// tsup's declaration bundler mis-compiles a type re-export in that position: it\n// emitted `declare const types_MPFRole: typeof MPFRole;` — a *value* declaration\n// for a type — which makes the shipped .d.ts fail to compile with\n// `TS2693: 'MPFRole' only refers to a type, but is being used as a value here`.\n//\n// Invisible in this repo because our tsconfig sets `skipLibCheck: true`; a\n// consumer building with `skipLibCheck: false` gets a hard error. Found by\n// typechecking the packed tarball from outside the workspace.\n//\n// `MPFRole` is still exported from the root barrel and from the `/auth` subpath\n// via `src/auth/claims-types.ts`, which is where it belongs.\n\n/**\n * Roles accepted when WRITING a membership (inviting a member, updating a\n * role).\n *\n * Closed on purpose, and only here: on a request, autocomplete earns its keep\n * and an unknown role is a client bug worth catching at compile time.\n *\n * On RESPONSES the role is {@link MPFRole} (= `string`) instead. Roles are\n * database rows (`identity.tenant_membership_valid_roles`), so closing the union\n * on server output means a newly seeded role forces an SDK release — and it is\n * exactly how the fictional `'viewer'` role ended up in these types in five\n * places while the DB actually seeds `guest`.\n */\nexport type MPFTenantRoleInput = 'owner' | 'admin' | 'member' | 'guest';\n\n// ============================================================================\n// Request Types\n// ============================================================================\n\n/**\n * Request body for user registration\n */\nexport interface CreateUserRequest {\n /** User's email address */\n email: string;\n /** User's password (minimum 8 characters) */\n password: string;\n /** User's display name */\n display_name?: string;\n /** User's first name */\n first_name?: string;\n /** User's last name */\n last_name?: string;\n}\n\n/**\n * Request body for user login\n */\nexport interface LoginRequest {\n /** User's email address */\n email: string;\n /** User's password */\n password: string;\n}\n\n/**\n * Request body for profile update\n */\nexport interface UpdateProfileRequest {\n /** User's display name */\n display_name?: string;\n /** User's first name */\n first_name?: string;\n /** User's last name */\n last_name?: string;\n /** Custom user metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Request body for adding an email\n */\nexport interface AddEmailRequest {\n /** Email address to add */\n email: string;\n}\n\n/**\n * Request body for adding a phone number\n */\nexport interface AddPhoneRequest {\n /** Phone number in E.164 format */\n phone_number: string;\n}\n\n/**\n * Request body for verifying email or phone\n */\nexport interface VerifyContactRequest {\n /** 6-digit verification code */\n code: string;\n}\n\n/**\n * Request body for sending password recovery code\n */\nexport interface SendRecoveryCodeRequest {\n /** User's email address */\n email: string;\n}\n\n/**\n * Request body for verifying recovery code\n */\nexport interface VerifyRecoveryCodeRequest {\n /** User's email address */\n email: string;\n /** 6-digit verification code */\n verification_code: string;\n}\n\n/**\n * Request body for password reset\n */\nexport interface ResetPasswordRequest {\n /** Recovery token obtained from verification step */\n recovery_token: string;\n /** New password to set (minimum 8 characters) */\n new_password: string;\n}\n\n/**\n * Request body for authenticated password update\n */\nexport interface UpdatePasswordRequest {\n /** Current password for verification */\n current_password: string;\n /** New password to set (minimum 8 characters) */\n new_password: string;\n}\n\n/**\n * Request body for session renewal\n */\nexport interface RenewSessionRequest {\n /** The refresh token from the current session */\n refresh_token: string;\n}\n\n/**\n * Request body for session revocation\n */\nexport interface RevokeSessionRequest {\n /** The refresh token of the session to revoke */\n refresh_token: string;\n}\n\n/**\n * Request body for tenant creation\n */\nexport interface CreateTenantRequest {\n /** Name of the tenant organization */\n name: string;\n /** URL-friendly slug (auto-generated from name if omitted) */\n slug?: string;\n /** Optional description of the tenant */\n description?: string;\n}\n\n/**\n * Request body for inviting a member\n */\nexport interface InviteMemberRequest {\n /** Email address of the person to invite */\n email: string;\n /** Role to assign to the invited member */\n role: MPFTenantRoleInput;\n /**\n * Optional override for the configured accept URL template. The literal\n * \"{token}\" is replaced with the invitation token.\n */\n accept_url_template?: string;\n}\n\n/**\n * Result of POST /tenants/{id}/members/invite.\n */\nexport interface InvitationResponse {\n invitation_id: string;\n invite_token: string;\n /** Copyable URL the invitee can use; safe fallback if email delivery fails. */\n accept_url: string;\n email: string;\n role: string;\n expires_at: string;\n /** True when no existing user matches the invited email. */\n is_new_user: boolean;\n /** True when the invitation email was successfully dispatched. */\n email_sent: boolean;\n /** Legacy field. Always empty in the new invitation flow. */\n membership_id?: string;\n}\n\n/**\n * Public, pre-auth view of an invitation. Email is intentionally omitted.\n */\nexport interface InvitationPreviewResponse {\n tenant_id: string;\n tenant_name: string;\n tenant_slug?: string;\n role: string;\n inviter_display_name?: string;\n expires_at: string;\n /** True when the invitee has no verified account yet. */\n requires_signup: boolean;\n}\n\n/**\n * Result of POST /invitations/{token}/accept.\n */\nexport interface AcceptInvitationResponse {\n invitation_id: string;\n tenant_id: string;\n role: string;\n membership_id: string;\n accepted_at: string;\n}\n\n/**\n * Request body for updating member role\n */\nexport interface UpdateMemberRoleRequest {\n /** New role for the member */\n role: MPFTenantRoleInput;\n}\n\n// ============================================================================\n// TOTP (Two-Factor Authentication) Types\n// ============================================================================\n\n/**\n * Request body for verifying a TOTP code\n */\nexport interface VerifyTOTPRequest {\n /** 6-digit TOTP code from authenticator app */\n code: string;\n}\n\n/**\n * Request body for disabling TOTP\n */\nexport interface DisableTOTPRequest {\n /** 6-digit TOTP code to confirm disable */\n code: string;\n}\n\n/**\n * Request body for deleting a passkey (optional, required when user has TOTP 2FA enabled)\n */\nexport interface DeletePasskeyRequest {\n /** 6-digit TOTP code from authenticator app */\n totp_code?: string;\n}\n\n// ============================================================================\n// Passkey / WebAuthn Types\n// ============================================================================\n\n/** WebAuthn credential descriptor as serialized by the API */\nexport interface WebAuthnCredentialDescriptor {\n type: string;\n id: string;\n transports?: string[];\n}\n\n/** WebAuthn creation options as serialized by the API (base64url strings, not ArrayBuffers) */\nexport interface WebAuthnCreationOptions {\n rp: { id: string; name: string };\n user: { id: string; name: string; displayName: string };\n challenge: string;\n pubKeyCredParams: Array<{ type: string; alg: number }>;\n timeout?: number;\n excludeCredentials?: WebAuthnCredentialDescriptor[];\n authenticatorSelection?: {\n authenticatorAttachment?: string;\n residentKey?: string;\n requireResidentKey?: boolean;\n userVerification?: string;\n };\n attestation?: string;\n hints?: string[];\n extensions?: Record<string, unknown>;\n}\n\n/** WebAuthn request options as serialized by the API (base64url strings, not ArrayBuffers) */\nexport interface WebAuthnRequestOptions {\n challenge: string;\n rpId?: string;\n timeout?: number;\n allowCredentials?: WebAuthnCredentialDescriptor[];\n userVerification?: string;\n hints?: string[];\n extensions?: Record<string, unknown>;\n}\n\n/** Encoded credential sent back to the server after navigator.credentials.create/get */\nexport interface WebAuthnEncodedCredential {\n id: string;\n rawId: string;\n type: string;\n response: {\n clientDataJSON: string;\n attestationObject?: string;\n authenticatorData?: string;\n signature?: string;\n userHandle?: string | null;\n };\n}\n\n/**\n * Request body for completing passkey registration\n */\nexport interface FinishPasskeyRegistrationRequest {\n /** Raw WebAuthn credential from navigator.credentials.create() */\n credential: WebAuthnEncodedCredential;\n /** Optional human-readable name for the passkey */\n name?: string;\n}\n\n/**\n * Request body for completing passkey login\n */\nexport interface FinishPasskeyLoginRequest {\n /** Raw WebAuthn credential from navigator.credentials.get() */\n credential: WebAuthnEncodedCredential;\n /** Session key returned from begin login */\n session_key: string;\n}\n\n// ============================================================================\n// Google OAuth Types\n// ============================================================================\n\n/**\n * Request body for Google OAuth callback\n */\nexport interface GoogleOAuthCallbackRequest {\n /** Authorization code from Google */\n code: string;\n /** Redirect URI used in the initial auth request */\n redirect_uri: string;\n /**\n * The `state` returned by `getGoogleOAuthURL`, round-tripped through the\n * redirect.\n *\n * **Required, and required for a reason.** It is the CSRF defence for this\n * flow: the server validates it before exchanging the code, so a callback\n * carrying an attacker's `code` but not the victim's `state` is rejected.\n * Without it, an attacker can sign a victim into the attacker's own account —\n * confirmed exploitable, not hypothetical.\n *\n * Persist it across the redirect with `createOAuthStateStore()` (web storage:\n * a full-page redirect discards anything held in memory).\n */\n state: string;\n}\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\n/**\n * Response containing access and refresh tokens\n */\nexport interface AccessDataResponse {\n /** JWT access token for API authentication */\n access_token: string;\n /** Refresh token for session renewal */\n refresh_token: string;\n}\n\n/**\n * User profile information\n */\nexport interface UserProfileResponse {\n /** User's unique identifier */\n id: string;\n /** User's display name */\n display_name?: string;\n /** User's first name */\n first_name?: string;\n /** User's last name */\n last_name?: string;\n /** User's avatar URL */\n avatar_url?: string;\n /** User's email addresses */\n emails: EmailResponse[];\n /** User's phone numbers */\n phones: PhoneResponse[];\n}\n\n/**\n * Email address information\n */\nexport interface EmailResponse {\n /** Email's unique identifier */\n id: string;\n /** Email address */\n email: string;\n /** Whether this is the primary email */\n is_primary: boolean;\n /** When the email was verified (ISO 8601), undefined if not verified */\n verified_at?: string;\n}\n\n/**\n * Phone number information\n */\nexport interface PhoneResponse {\n /** Phone's unique identifier */\n id: string;\n /** Phone number in E.164 format */\n phone_number: string;\n /** Whether this is the primary phone */\n is_primary: boolean;\n /** When the phone was verified (ISO 8601), undefined if not verified */\n verified_at?: string;\n}\n\n/**\n * Session client information\n */\nexport interface SessionClientInfo {\n /** Client name */\n name?: string;\n /** Client user agent string */\n user_agent?: string;\n /** Client IP address */\n ip_address?: string;\n /** When the client was last seen (ISO 8601) */\n last_seen_at?: string;\n}\n\n/**\n * Session information\n */\nexport interface SessionResponse {\n /** Session's unique identifier */\n id: string;\n /** Client ID associated with the session */\n client_id: string;\n /** Client information */\n client?: SessionClientInfo;\n /** When the session expires (ISO 8601) */\n expires_at: string;\n /** When the session was created (ISO 8601) */\n created_at: string;\n /** Whether this is the current session */\n is_current: boolean;\n}\n\n/**\n * OAuth client information\n */\nexport interface ClientResponse {\n /** Client's unique identifier */\n id: string;\n /** Client name */\n name?: string;\n /** Client user agent string */\n user_agent?: string;\n /** Client IP address */\n ip_address?: string;\n /** When the client was last seen (ISO 8601) */\n last_seen_at?: string;\n}\n\n/**\n * Tenant information\n */\nexport interface TenantResponse {\n /** Tenant's unique identifier */\n id: string;\n /** Tenant name */\n name: string;\n /** Tenant description */\n description?: string;\n /** Tenant slug (URL-friendly identifier) */\n slug?: string;\n /** When the tenant was created (ISO 8601) */\n created_at: string;\n}\n\n/**\n * Tenant membership information\n */\nexport interface MembershipResponse {\n /** Membership unique identifier */\n id: string;\n /** User's unique identifier */\n user_id: string;\n /** Member's role in the tenant */\n role: MPFRole;\n /** When the member was invited (ISO 8601) */\n invited_at?: string;\n /** When the invitation was accepted (ISO 8601) */\n accepted_at?: string;\n /** Member's display name */\n display_name?: string;\n /** Member's email address */\n email?: string;\n}\n\n/**\n * Response containing recovery token\n */\nexport interface RecoveryTokenResponse {\n /** Token to use for password reset */\n recovery_token: string;\n}\n\n/**\n * Simple success response\n */\nexport interface SuccessResponse {\n /** Indicates if the operation was successful */\n success: boolean;\n}\n\n/**\n * Error response from the API\n */\nexport interface ErrorResponse {\n /** Human-readable error message */\n error: string;\n /** Machine-readable error code */\n code?: string;\n /** Additional error details (validation errors, etc.) */\n details?: unknown;\n}\n\n/**\n * Validation error detail for a specific field\n */\nexport interface ValidationErrorDetail {\n /** Name of the field with validation error */\n field: string;\n /** Validation error message */\n message: string;\n}\n\n/**\n * Service health status response\n */\nexport interface HealthResponse {\n /** Health status */\n status: string;\n /** Service name */\n service: string;\n /** Current server timestamp (ISO 8601) */\n timestamp: string;\n}\n\n// ============================================================================\n// TOTP Response Types\n// ============================================================================\n\n/**\n * Response from TOTP setup containing secret and backup codes\n */\nexport interface TOTPSetupResponse {\n /** TOTP secret key for manual entry */\n secret: string;\n /** otpauth:// URL for QR code generation */\n qr_url: string;\n /** One-time backup codes for account recovery */\n backup_codes: string[];\n}\n\n// ============================================================================\n// Passkey Response Types\n// ============================================================================\n\n/**\n * Response from begin passkey registration\n */\nexport interface BeginPasskeyRegistrationResponse {\n /** WebAuthn PublicKeyCredentialCreationOptions */\n options: WebAuthnCreationOptions;\n}\n\n/**\n * Response from begin passkey login\n */\nexport interface BeginPasskeyLoginResponse {\n /** WebAuthn PublicKeyCredentialRequestOptions */\n options: WebAuthnRequestOptions;\n /** Session key to pass back in finish login */\n session_key: string;\n}\n\n/**\n * Passkey credential information\n */\nexport interface PasskeyResponse {\n /** Passkey's unique identifier */\n id: string;\n /** Human-readable name for the passkey */\n name?: string;\n /** When the passkey was registered (ISO 8601) */\n created_at: string;\n /** When the passkey was last used (ISO 8601) */\n last_used_at?: string;\n}\n\n// ============================================================================\n// OAuth Response Types\n// ============================================================================\n\n/**\n * A pending invitation for the current user\n */\nexport interface PendingInvitationResponse {\n /** Invitation/membership ID */\n id: string;\n /** Tenant ID the invitation is for */\n tenant_id: string;\n /** Tenant name */\n tenant_name: string;\n /** Tenant slug */\n tenant_slug?: string;\n /** Role assigned in the invitation */\n role: MPFRole;\n /** User ID of the person who sent the invitation */\n invited_by: string;\n /** When the invitation was sent (ISO 8601) */\n invited_at: string;\n /** Invitation token for accepting */\n token: string;\n}\n\n/**\n * A pending invitation issued by the authenticated caller, returned by\n * GET /tenants/{id}/invitations.\n */\nexport interface IssuedInvitationResponse {\n /** Invitation ID */\n id: string;\n /** Tenant the invitation was issued for */\n tenant_id: string;\n /** Email the invitation was sent to */\n email: string;\n /** Role the invitee will receive on accept */\n role: MPFRole;\n /** User ID of the inviter (always the authenticated caller) */\n invited_by: string;\n /** When the invitation was sent (ISO 8601) */\n invited_at: string;\n /** Expiration time (ISO 8601) */\n expires_at: string;\n /** Raw token. Most callers should use accept_url instead. */\n token: string;\n /**\n * Copyable URL the invitee can paste into a browser. Empty if the server\n * has no accept-URL template configured.\n */\n accept_url: string;\n /** Display name of the invitee, if they already have an account */\n display_name?: string;\n}\n\n/**\n * Response containing Google OAuth authorization URL\n */\nexport interface GoogleOAuthURLResponse {\n /** Full Google OAuth authorization URL to redirect user to */\n url: string;\n /**\n * Single-use CSRF state minted and recorded by the server.\n *\n * Persist this before redirecting and send it back on\n * `handleGoogleOAuthCallback`. Dropping it makes the callback trivially\n * forgeable — see {@link GoogleOAuthCallbackRequest.state}.\n */\n state: string;\n}\n\n// ============================================================================\n// List Wrapper Response Types\n// ============================================================================\n\n/**\n * Wrapper response for email list\n */\nexport interface EmailsResponse {\n emails: EmailResponse[];\n}\n\n/**\n * Wrapper response for phone list\n */\nexport interface PhonesResponse {\n phones: PhoneResponse[];\n}\n\n/**\n * Wrapper response for session list\n */\nexport interface SessionsResponse {\n sessions: SessionResponse[];\n}\n\n/**\n * Wrapper response for passkey list\n */\nexport interface PasskeysResponse {\n passkeys: PasskeyResponse[];\n}\n\n/**\n * Wrapper response for client list\n */\nexport interface ClientsResponse {\n clients: ClientResponse[];\n}\n\n/**\n * Wrapper response for member list\n */\nexport interface MembersResponse {\n members: MembershipResponse[];\n}\n\n/**\n * Wrapper response for pending-invitations-issued-by-caller list\n */\nexport interface IssuedInvitationsResponse {\n invitations: IssuedInvitationResponse[];\n}\n\n// ============================================================================\n// MFA Response Types\n// ============================================================================\n\n/**\n * Returned when MFA verification is needed to complete login\n */\nexport interface MFARequiredResponse {\n /** Always true for this response type */\n mfa_required: true;\n /** Short-lived JWT ticket for MFA verification */\n mfa_ticket: string;\n /** Available MFA methods (e.g., [\"totp\"]) */\n mfa_methods: string[];\n}\n\n/**\n * Returned when MFA setup is enforced and user hasn't set up TOTP yet\n */\nexport interface MFASetupRequiredResponse {\n /** Always true for this response type */\n mfa_setup_required: true;\n /** Short-lived JWT ticket for MFA setup verification */\n mfa_ticket: string;\n /** TOTP setup data including secret and QR code */\n totp_setup: TOTPSetupResponse;\n}\n\n/**\n * Union type for all possible login responses\n */\nexport type LoginResponse = AccessDataResponse | MFARequiredResponse | MFASetupRequiredResponse;\n\n/**\n * Type guard to check if login response requires MFA verification\n */\nexport function isMFARequired(response: LoginResponse): response is MFARequiredResponse {\n return 'mfa_required' in response && response.mfa_required === true;\n}\n\n/**\n * Type guard to check if login response requires MFA setup\n */\nexport function isMFASetupRequired(response: LoginResponse): response is MFASetupRequiredResponse {\n return 'mfa_setup_required' in response && response.mfa_setup_required === true;\n}\n\n// ============================================================================\n// MFA Request Types\n// ============================================================================\n\n/**\n * Request body for verifying MFA during login\n */\nexport interface MFAVerifyRequest {\n /** MFA ticket from login response */\n mfa_ticket: string;\n /** 6-digit TOTP code from authenticator app */\n totp_code: string;\n}\n\n/**\n * Request body for verifying MFA setup during first-time enrollment\n */\nexport interface MFASetupVerifyRequest {\n /** MFA ticket from login response */\n mfa_ticket: string;\n /** 6-digit TOTP code to verify setup */\n code: string;\n}\n"]}
1
+ {"version":3,"sources":["../src/identity/index.ts","../src/identity/v0.ts","../src/identity/types.ts"],"names":[],"mappings":"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","file":"chunk-R5KABORE.js","sourcesContent":["import type { ClientConfig, TokenProvider } from '../client/core/types.js';\nimport { attachStandardMiddlewares } from '../client/core/client-factory.js';\nimport { createTurnstileMiddleware } from '../client/middlewares/turnstile.js';\nimport {\n createAdminAuthMiddleware,\n type AdminAuthMiddlewareOptions,\n} from '../client/middlewares/admin-auth.js';\nimport type { TenantSelectionStore } from '../auth/tenant-selection.js';\nimport type { OAuthStateStore } from '../auth/oauth-state.js';\nimport { AuthClientV0 } from './v0.js';\n\n/**\n * Provider for minting single-use Cloudflare Turnstile tokens.\n */\nexport interface TurnstileProvider {\n /** Mint a fresh single-use Turnstile token. */\n getToken: () => Promise<string>;\n}\n\n/**\n * Configuration options for the Auth client\n */\nexport interface AuthClientOptions extends Omit<ClientConfig, 'baseUrl'> {\n /**\n * Base URL for the Auth service\n */\n baseUrl: string;\n /** Optional token provider. Auto-wires auth middleware when provided. */\n tokenProvider?: TokenProvider;\n /** Optional Turnstile token provider for bot protection. */\n turnstileProvider?: TurnstileProvider;\n /**\n * Optional shared tenant selection. When provided, every request carries the\n * selected tenant headers. Construct it with `createTenantSelection()` and\n * share the same instance across identity/storage/graphql clients.\n */\n tenantProvider?: TenantSelectionStore;\n /**\n * Optional store for the OAuth CSRF state. When provided,\n * `getGoogleOAuthURL` persists the minted state so it survives the redirect.\n * Build one with `createOAuthStateStore()`.\n */\n oauthStateStore?: OAuthStateStore;\n}\n\n/**\n * Creates an Auth client for API v0\n *\n * @param options - Client configuration options\n * @returns AuthClientV0 instance\n *\n * @example\n * ```typescript\n * import { createAuthClient } from '@mosano-product-framework/sdk/identity';\n *\n * // Create client without authentication (for public endpoints)\n * const auth = createAuthClient({\n * baseUrl: 'https://api.example.com/auth',\n * });\n *\n * // Register a new user\n * const { access_token, refresh_token } = await auth.signUpEmailPassword({\n * name: 'John Doe',\n * email: 'john@example.com',\n * password: 'securePassword123',\n * });\n *\n * // Create authenticated client with token provider\n * const authenticatedAuth = createAuthClient({\n * baseUrl: 'https://api.example.com/auth',\n * tokenProvider: {\n * getAccessToken: () => localStorage.getItem('accessToken'),\n * onTokenExpired: () => { window.location.href = '/login'; },\n * },\n * });\n *\n * // Get user profile\n * const profile = await authenticatedAuth.getMe();\n * ```\n */\n/**\n * SDK endpoint paths that require a Turnstile token.\n * Must match the go-identity routes with turnstile.Verify() middleware.\n */\nconst TURNSTILE_PROTECTED_PATHS = [\n '/sign-up-email-password',\n '/sign-in-email-password',\n '/forgot-password-with-email',\n '/password/recovery/verify',\n '/password/reset',\n '/passkey/login/begin',\n '/passkey/login/finish',\n '/oauth/google/callback',\n '/accept', // matches /invitations/{token}/accept\n '/invite', // matches /tenants/{id}/members/invite\n];\n\nexport function createAuthClient(options: AuthClientOptions): AuthClientV0 {\n const { tokenProvider, turnstileProvider, tenantProvider, ...clientConfig } = options;\n const client = new AuthClientV0(clientConfig);\n\n attachStandardMiddlewares(client, { tokenProvider, tenantProvider });\n\n if (turnstileProvider) {\n client.use(createTurnstileMiddleware({\n getToken: turnstileProvider.getToken,\n protectedPaths: TURNSTILE_PROTECTED_PATHS,\n }));\n }\n\n return client;\n}\n\n/**\n * Configuration options for an admin-authenticated Auth client.\n *\n * SECURITY: Admin authentication uses the shared `ADMIN_JWT_SECRET`, which can\n * impersonate any user. Only construct an admin client server-side / in trusted\n * services. NEVER ship the secret to a browser.\n */\nexport interface AdminClientOptions extends Omit<ClientConfig, 'baseUrl'> {\n /** Base URL for the Auth service. */\n baseUrl: string;\n /** Admin auth options: either a pre-minted `token` or a minting `config`. */\n admin: AdminAuthMiddlewareOptions;\n}\n\n/**\n * Creates an admin-authenticated Auth client for API v0.\n *\n * The returned client sends `Authorization: Admin <jwt>` on every request,\n * acting on behalf of the configured principal. Mirrors {@link createAuthClient}\n * but wires the admin auth middleware instead of the Bearer one.\n *\n * SECURITY: Requires the shared `ADMIN_JWT_SECRET` (when using a minting\n * `config`). Server-side / trusted-service use ONLY — never expose the secret\n * to a browser.\n *\n * @param options - Client configuration options.\n * @returns AuthClientV0 instance authenticated as an admin.\n *\n * @example\n * ```typescript\n * import { createAdminClient } from '@mosano-product-framework/sdk/identity';\n *\n * // Mint a fresh admin token per request (server-side only).\n * const admin = createAdminClient({\n * baseUrl: 'https://api.example.com/auth',\n * admin: {\n * config: {\n * secret: process.env.ADMIN_JWT_SECRET!,\n * actOnBehalfOf: { userId, onTenantId: tenantId },\n * ttlSeconds: 60,\n * },\n * },\n * });\n * ```\n */\nexport function createAdminClient(options: AdminClientOptions): AuthClientV0 {\n const { admin, ...clientConfig } = options;\n const client = new AuthClientV0(clientConfig);\n client.use(createAdminAuthMiddleware(admin));\n return client;\n}\n\nexport { AuthClientV0, type AuthClientV0Config } from './v0.js';\nexport * from './types.js';\n","import { MPFClient } from '../client/core/client.js';\nimport type { ClientConfig, RequestOptions } from '../client/core/types.js';\nimport { MPFValidationError } from '../client/core/errors.js';\nimport type { OAuthStateStore } from '../auth/oauth-state.js';\nimport type * as Types from './types.js';\n\n/**\n * Configuration for the identity client.\n */\nexport interface AuthClientV0Config extends ClientConfig {\n /**\n * Optional store for the OAuth CSRF state. When provided,\n * `getGoogleOAuthURL` persists the minted state automatically so it survives\n * the redirect.\n *\n * Sending it back stays explicit — `GoogleOAuthCallbackRequest.state` is\n * required — because a security parameter should not be injected invisibly.\n */\n oauthStateStore?: OAuthStateStore;\n}\n\n/**\n * Auth API v0 client\n *\n * Provides methods for authentication, user management, sessions,\n * password recovery, and multi-tenant operations.\n */\nexport class AuthClientV0 extends MPFClient {\n /** Optional OAuth state store; see {@link AuthClientV0Config.oauthStateStore}. */\n private readonly oauthStateStore?: OAuthStateStore;\n\n constructor(config: AuthClientV0Config) {\n const { oauthStateStore, ...clientConfig } = config;\n super({\n ...clientConfig,\n baseUrl: `${clientConfig.baseUrl}/v0`,\n });\n this.oauthStateStore = oauthStateStore;\n }\n\n /**\n * Wraps request options with skipAuth: true for public endpoints\n * that do not require authentication headers.\n */\n private publicOptions(options?: RequestOptions): RequestOptions {\n return { ...options, skipAuth: true };\n }\n\n // ============================================================================\n // Public Endpoints - Authentication\n // ============================================================================\n\n /**\n * Register a new user with email and password\n *\n * Creates a new user account and returns access and refresh tokens.\n *\n * @param data - User registration data\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async signUpEmailPassword(\n data: Types.CreateUserRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n const cleanedData = {\n email: data.email,\n password: data.password,\n ...(data.first_name ? { first_name: data.first_name } : {}),\n ...(data.last_name ? { last_name: data.last_name } : {}),\n ...(data.display_name ? { display_name: data.display_name } : {}),\n };\n return this.post<Types.AccessDataResponse>(\n '/sign-up-email-password',\n cleanedData,\n this.publicOptions(options)\n );\n }\n\n /**\n * Login with email and password\n *\n * Authenticates a user and returns access and refresh tokens.\n *\n * @param data - Login credentials\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async signInEmailPassword(\n data: Types.LoginRequest,\n options?: RequestOptions\n ): Promise<Types.LoginResponse> {\n return this.post<Types.LoginResponse>(\n '/sign-in-email-password',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Verify MFA code to complete login\n *\n * After a login attempt returns mfa_required, submit the TOTP code\n * along with the MFA ticket to complete authentication.\n *\n * @param data - MFA ticket and TOTP code\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async verifyMFA(\n data: Types.MFAVerifyRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/mfa/verify',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Verify MFA setup to complete first-time enrollment and login\n *\n * After a login attempt returns mfa_setup_required, verify the TOTP\n * setup by submitting a code from the authenticator app.\n *\n * @param data - MFA ticket and verification code\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async verifyMFASetup(\n data: Types.MFASetupVerifyRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/mfa/setup/verify',\n data,\n this.publicOptions(options)\n );\n }\n\n // ============================================================================\n // Public Endpoints - Password Recovery\n // ============================================================================\n\n /**\n * Send password recovery code to email\n *\n * Initiates the password recovery process by sending a verification code.\n *\n * @param data - Email address for recovery\n * @param options - Optional request options\n * @returns Success response\n */\n async forgotPasswordWithEmail(\n data: Types.SendRecoveryCodeRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n '/forgot-password-with-email',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Verify password recovery code\n *\n * Verifies the recovery code and returns a recovery token for password reset.\n *\n * @param data - Email and verification code\n * @param options - Optional request options\n * @returns Recovery token for password reset\n */\n async verifyRecoveryCode(\n data: Types.VerifyRecoveryCodeRequest,\n options?: RequestOptions\n ): Promise<Types.RecoveryTokenResponse> {\n return this.post<Types.RecoveryTokenResponse>(\n '/password/recovery/verify',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Reset password with recovery token\n *\n * Resets the user's password and returns new access and refresh tokens.\n *\n * @param data - Recovery token and new password\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async resetPassword(\n data: Types.ResetPasswordRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/password/reset',\n data,\n this.publicOptions(options)\n );\n }\n\n // ============================================================================\n // Public Endpoints - Sessions\n // ============================================================================\n\n /**\n * Renew session with refresh token\n *\n * Exchanges a valid refresh token for new access and refresh tokens.\n *\n * Tenant is selected per request via the `X-MPF-Tenant` header, so a renewal\n * neither takes nor changes a tenant.\n *\n * @param data - Refresh token\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async renewSession(\n data: Types.RenewSessionRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/sessions/renew',\n data,\n this.publicOptions(options)\n );\n }\n\n /**\n * Revoke session (logout)\n *\n * Revokes the session associated with the provided refresh token.\n * Requires authentication.\n *\n * @param data - Refresh token to revoke\n * @param options - Optional request options\n * @returns Success response\n */\n async revokeSession(\n data: Types.RevokeSessionRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n '/sessions/revoke',\n data,\n options\n );\n }\n\n // ============================================================================\n // Public Endpoints - Invitations\n // ============================================================================\n\n /**\n * List pending invitations for the authenticated user\n *\n * Returns all pending invitations for the currently authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of pending invitations\n */\n async listMyInvitations(\n options?: RequestOptions\n ): Promise<Types.PendingInvitationResponse[]> {\n return this.get<Types.PendingInvitationResponse[]>(\n '/users/me/invitations',\n options\n );\n }\n\n /**\n * Preview an invitation (public, pre-auth).\n *\n * Returns the tenant, role, and inviter display name for the\n * invitation-acceptance page. Email is intentionally omitted. Use this\n * to render the accept page before the user signs in.\n *\n * @param token - Invitation token\n * @param options - Optional request options\n * @returns Public-safe invitation preview\n */\n async previewInvitation(\n token: string,\n options?: RequestOptions\n ): Promise<Types.InvitationPreviewResponse> {\n return this.get<Types.InvitationPreviewResponse>(\n `/invitations/${encodeURIComponent(token)}`,\n this.publicOptions(options)\n );\n }\n\n /**\n * Accept an invitation.\n *\n * Requires the user to be authenticated. The user's primary verified\n * email must match the invitation. Creates the membership row.\n *\n * @param token - Invitation token\n * @param options - Optional request options\n * @returns Acceptance result (invitation + new membership)\n */\n async acceptInvitation(\n token: string,\n options?: RequestOptions\n ): Promise<Types.AcceptInvitationResponse> {\n return this.post<Types.AcceptInvitationResponse>(\n `/invitations/${encodeURIComponent(token)}/accept`,\n undefined,\n options\n );\n }\n\n /**\n * Revoke a pending invitation. Caller must be a manager of the tenant\n * that issued the invitation.\n *\n * @param invitationId - Invitation ID (not the token)\n * @param options - Optional request options\n */\n async revokeInvitation(\n invitationId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/invitations/${encodeURIComponent(invitationId)}`,\n options\n );\n }\n\n // ============================================================================\n // Public Endpoints - Health\n // ============================================================================\n\n /**\n * Health check endpoint\n *\n * Returns the health status of the service.\n *\n * @param options - Optional request options\n * @returns Health status\n */\n async healthCheck(options?: RequestOptions): Promise<Types.HealthResponse> {\n return this.get<Types.HealthResponse>('/healthz', this.publicOptions(options));\n }\n\n // ============================================================================\n // Protected Endpoints - User Profile\n // ============================================================================\n\n /**\n * Get current user profile\n *\n * Returns the authenticated user's profile information.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns User profile\n */\n async getMe(options?: RequestOptions): Promise<Types.UserProfileResponse> {\n return this.get<Types.UserProfileResponse>('/users/me', options);\n }\n\n /**\n * Update current user profile\n *\n * Updates the authenticated user's profile information.\n * Requires authentication.\n *\n * @param data - Profile update data\n * @param options - Optional request options\n * @returns Updated user profile\n */\n async updateMe(\n data: Types.UpdateProfileRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.patch<Types.SuccessResponse>('/users/me', data, options);\n }\n\n // ============================================================================\n // Protected Endpoints - Emails\n // ============================================================================\n\n /**\n * List user emails\n *\n * Returns all email addresses associated with the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of email addresses\n */\n async listEmails(options?: RequestOptions): Promise<Types.EmailResponse[]> {\n const response = await this.get<Types.EmailsResponse>('/users/me/emails', options);\n return response.emails;\n }\n\n /**\n * Add a new email address\n *\n * Adds a new email address to the authenticated user's account.\n * A verification code will be sent to the email.\n * Requires authentication.\n *\n * @param data - Email address to add\n * @param options - Optional request options\n * @returns Added email information\n */\n async addEmail(\n data: Types.AddEmailRequest,\n options?: RequestOptions\n ): Promise<Types.EmailResponse> {\n return this.post<Types.EmailResponse>('/users/me/emails', data, options);\n }\n\n /**\n * Verify an email address\n *\n * Verifies an email address using a verification code.\n * Requires authentication.\n *\n * @param emailId - Email ID to verify\n * @param data - Verification code\n * @param options - Optional request options\n * @returns Success response\n */\n async verifyEmail(\n emailId: string,\n data: Types.VerifyContactRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n `/users/me/emails/${encodeURIComponent(emailId)}/verify`,\n data,\n options\n );\n }\n\n /**\n * Delete an email address\n *\n * Removes an email address from the authenticated user's account.\n * Cannot delete the primary email.\n * Requires authentication.\n *\n * @param emailId - Email ID to delete\n * @param options - Optional request options\n * @returns Success response\n */\n async deleteEmail(\n emailId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/users/me/emails/${encodeURIComponent(emailId)}`,\n undefined,\n options\n );\n }\n\n /**\n * Set email as primary\n *\n * Sets the specified email address as the primary email for the user.\n * Email must be verified before it can be set as primary.\n * Requires authentication.\n *\n * @param emailId - Email ID to set as primary\n * @param options - Optional request options\n * @returns Success response\n */\n async setPrimaryEmail(\n emailId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n `/users/me/emails/${encodeURIComponent(emailId)}/set-primary`,\n undefined,\n options\n );\n }\n\n /**\n * Send email verification code\n *\n * Sends a verification code to the authenticated user's primary email address.\n * Use verifyEmail() to complete the verification.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Success response\n */\n async sendEmailVerification(\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n '/email/send-verification',\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Phones\n // ============================================================================\n\n /**\n * List user phones\n *\n * Returns all phone numbers associated with the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of phone numbers\n */\n async listPhones(options?: RequestOptions): Promise<Types.PhoneResponse[]> {\n const response = await this.get<Types.PhonesResponse>('/users/me/phones', options);\n return response.phones;\n }\n\n /**\n * Add a new phone number\n *\n * Adds a new phone number to the authenticated user's account.\n * A verification code will be sent to the phone.\n * Requires authentication.\n *\n * @param data - Phone number to add (E.164 format)\n * @param options - Optional request options\n * @returns Added phone information\n */\n async addPhone(\n data: Types.AddPhoneRequest,\n options?: RequestOptions\n ): Promise<Types.PhoneResponse> {\n return this.post<Types.PhoneResponse>('/users/me/phones', data, options);\n }\n\n /**\n * Verify a phone number\n *\n * Verifies a phone number using a verification code.\n * Requires authentication.\n *\n * @param phoneId - Phone ID to verify\n * @param data - Verification code\n * @param options - Optional request options\n * @returns Success response\n */\n async verifyPhone(\n phoneId: string,\n data: Types.VerifyContactRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n `/users/me/phones/${encodeURIComponent(phoneId)}/verify`,\n data,\n options\n );\n }\n\n /**\n * Delete a phone number\n *\n * Removes a phone number from the authenticated user's account.\n * Cannot delete the primary phone.\n * Requires authentication.\n *\n * @param phoneId - Phone ID to delete\n * @param options - Optional request options\n * @returns Success response\n */\n async deletePhone(\n phoneId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/users/me/phones/${encodeURIComponent(phoneId)}`,\n undefined,\n options\n );\n }\n\n /**\n * Set phone as primary\n *\n * Sets the specified phone number as the primary phone for the user.\n * Phone must be verified before it can be set as primary.\n * Requires authentication.\n *\n * @param phoneId - Phone ID to set as primary\n * @param options - Optional request options\n * @returns Success response\n */\n async setPrimaryPhone(\n phoneId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n `/users/me/phones/${encodeURIComponent(phoneId)}/set-primary`,\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Sessions\n // ============================================================================\n\n /**\n * List user sessions\n *\n * Returns all active sessions for the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of sessions\n */\n async listSessions(\n options?: RequestOptions\n ): Promise<Types.SessionResponse[]> {\n const response = await this.get<Types.SessionsResponse>('/users/me/sessions', options);\n return response.sessions;\n }\n\n /**\n * Delete a session\n *\n * Revokes a specific session for the authenticated user.\n * Requires authentication.\n *\n * @param sessionId - Session ID to delete\n * @param options - Optional request options\n * @returns Success response\n */\n async deleteSession(\n sessionId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/users/me/sessions/${encodeURIComponent(sessionId)}`,\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Clients\n // ============================================================================\n\n /**\n * List authorized OAuth clients\n *\n * Returns all OAuth clients authorized by the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of OAuth clients\n */\n async listClients(options?: RequestOptions): Promise<Types.ClientResponse[]> {\n const response = await this.get<Types.ClientsResponse>('/users/me/clients', options);\n return response.clients;\n }\n\n /**\n * Revoke OAuth client authorization\n *\n * Revokes authorization for a specific OAuth client.\n * Requires authentication.\n *\n * @param clientId - Client ID to revoke\n * @param options - Optional request options\n * @returns Success response\n */\n async deleteClient(\n clientId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/users/me/clients/${encodeURIComponent(clientId)}`,\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Password\n // ============================================================================\n\n /**\n * Update password (authenticated)\n *\n * Updates the authenticated user's password.\n * Requires authentication.\n *\n * @param data - Current and new password\n * @param options - Optional request options\n * @returns Success response\n */\n async updatePassword(\n data: Types.UpdatePasswordRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>(\n '/password/update',\n data,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - Tenants\n // ============================================================================\n\n /**\n * Create a new tenant\n *\n * Creates a new tenant organization. The authenticated user becomes the owner.\n * Requires authentication.\n *\n * @param data - Tenant creation data\n * @param options - Optional request options\n * @returns Created tenant information\n */\n async createTenant(\n data: Types.CreateTenantRequest,\n options?: RequestOptions\n ): Promise<Types.TenantResponse> {\n return this.post<Types.TenantResponse>('/tenants', data, options);\n }\n\n /**\n * List current user's tenants\n *\n * Returns all tenants the authenticated user is a member of.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of tenant information\n */\n async listMyTenants(\n options?: RequestOptions\n ): Promise<Types.TenantResponse[]> {\n return this.get<Types.TenantResponse[]>('/users/me/tenants', options);\n }\n\n // ============================================================================\n // Protected Endpoints - Tenant Members\n // ============================================================================\n\n /**\n * List tenant members\n *\n * Returns all members of the specified tenant.\n * Requires authentication and membership in the tenant.\n *\n * @param tenantId - Tenant ID\n * @param options - Optional request options\n * @returns Array of tenant members\n */\n async listTenantMembers(\n tenantId: string,\n options?: RequestOptions\n ): Promise<Types.MembershipResponse[]> {\n const response = await this.get<Types.MembersResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/members`,\n options\n );\n return response.members;\n }\n\n /**\n * Invite a member to tenant\n *\n * Sends an invitation to join the tenant. Requires authentication and\n * owner/admin role on the tenant.\n *\n * @param tenantId - Target tenant ID\n * @param data - Invitation data\n * @param options - Optional request options\n * @returns Invitation result, including a copyable accept_url\n */\n async inviteTenantMember(\n tenantId: string,\n data: Types.InviteMemberRequest,\n options?: RequestOptions\n ): Promise<Types.InvitationResponse> {\n return this.post<Types.InvitationResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/members/invite`,\n data,\n options\n );\n }\n\n /**\n * List pending invitations issued by the authenticated caller for a tenant.\n *\n * Returns only invitations whose `invited_by` matches the caller. Lets the\n * caller copy the `accept_url` of an invite they previously sent (for\n * example, to re-share if email delivery failed). Callers without a\n * membership, and members who never issued an invite for this tenant,\n * get an empty array.\n *\n * @param tenantId - Tenant ID\n * @param options - Optional request options\n * @returns Array of invitations issued by the caller\n */\n async listTenantInvitationsIssuedByMe(\n tenantId: string,\n options?: RequestOptions\n ): Promise<Types.IssuedInvitationResponse[]> {\n const response = await this.get<Types.IssuedInvitationsResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/invitations`,\n options\n );\n return response.invitations;\n }\n\n /**\n * Update member role\n *\n * Updates the role of a tenant member.\n * Requires authentication and owner role in the tenant.\n *\n * @param tenantId - Tenant ID\n * @param userId - User ID of the member\n * @param data - New role\n * @param options - Optional request options\n * @returns Updated membership information\n */\n async updateTenantMemberRole(\n tenantId: string,\n userId: string,\n data: Types.UpdateMemberRoleRequest,\n options?: RequestOptions\n ): Promise<Types.MembershipResponse> {\n return this.patch<Types.MembershipResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(userId)}`,\n data,\n options\n );\n }\n\n /**\n * Remove member from tenant\n *\n * Removes a member from the tenant.\n * Cannot remove the last owner.\n * Requires authentication and admin/owner role in the tenant.\n *\n * @param tenantId - Tenant ID\n * @param userId - User ID of the member to remove\n * @param options - Optional request options\n * @returns Success response\n */\n async removeTenantMember(\n tenantId: string,\n userId: string,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/tenants/${encodeURIComponent(tenantId)}/members/${encodeURIComponent(userId)}`,\n undefined,\n options\n );\n }\n\n // ============================================================================\n // Protected Endpoints - TOTP (Two-Factor Authentication)\n // ============================================================================\n\n /**\n * Setup TOTP two-factor authentication\n *\n * Initializes TOTP setup and returns the secret, QR code URL, and backup codes.\n * The setup must be verified with verifyTOTP() before it becomes active.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns TOTP setup data including secret and backup codes\n */\n async setupTOTP(\n options?: RequestOptions\n ): Promise<Types.TOTPSetupResponse> {\n return this.post<Types.TOTPSetupResponse>(\n '/totp/setup',\n undefined,\n options\n );\n }\n\n /**\n * Verify TOTP setup\n *\n * Verifies a TOTP code to complete the 2FA setup process.\n * After verification, TOTP will be required on future logins.\n * Requires authentication.\n *\n * @param data - TOTP verification code\n * @param options - Optional request options\n * @returns Success response\n */\n async verifyTOTP(\n data: Types.VerifyTOTPRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>('/totp/verify', data, options);\n }\n\n /**\n * Disable TOTP two-factor authentication\n *\n * Disables TOTP 2FA. Requires a valid TOTP code to confirm.\n * Requires authentication.\n *\n * @param data - TOTP code to confirm disable\n * @param options - Optional request options\n * @returns Success response\n */\n async disableTOTP(\n data: Types.DisableTOTPRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.post<Types.SuccessResponse>('/totp/disable', data, options);\n }\n\n // ============================================================================\n // Passkey / WebAuthn - Public Endpoints\n // ============================================================================\n\n /**\n * Begin passkey login\n *\n * Starts the WebAuthn authentication process.\n * Returns options to pass to navigator.credentials.get().\n *\n * @param options - Optional request options\n * @returns WebAuthn request options\n */\n async beginPasskeyLogin(\n options?: RequestOptions\n ): Promise<Types.BeginPasskeyLoginResponse> {\n const response = await this.post<Types.BeginPasskeyLoginResponse & { session_key?: string }>(\n '/passkey/login/begin',\n undefined,\n this.publicOptions(options)\n );\n // Handle both shapes: server may return { publicKey: {...} } or flat { challenge, ... }\n const raw = response.options as unknown as Record<string, unknown>;\n const opts = ('publicKey' in raw ? raw.publicKey : raw) as Types.WebAuthnRequestOptions;\n return { options: opts, session_key: response.session_key ?? '' };\n }\n\n /**\n * Complete passkey login\n *\n * Completes the WebAuthn authentication and returns access tokens.\n *\n * @param data - WebAuthn assertion result from navigator.credentials.get()\n * @param options - Optional request options\n * @returns Access and refresh tokens\n */\n async finishPasskeyLogin(\n data: Types.FinishPasskeyLoginRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n return this.post<Types.AccessDataResponse>(\n '/passkey/login/finish',\n data,\n this.publicOptions(options)\n );\n }\n\n // ============================================================================\n // Passkey / WebAuthn - Protected Endpoints\n // ============================================================================\n\n /**\n * Begin passkey registration\n *\n * Starts the WebAuthn registration process for the authenticated user.\n * Returns options to pass to navigator.credentials.create().\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns WebAuthn creation options\n */\n async beginPasskeyRegistration(\n options?: RequestOptions\n ): Promise<Types.BeginPasskeyRegistrationResponse> {\n const response = await this.post<Types.BeginPasskeyRegistrationResponse>(\n '/passkeys/register/begin',\n undefined,\n options\n );\n // Handle both shapes: server may return { publicKey: {...} } or flat { rp, user, ... }\n const raw = response.options as unknown as Record<string, unknown>;\n const opts = ('publicKey' in raw ? raw.publicKey : raw) as Types.WebAuthnCreationOptions;\n return { options: opts };\n }\n\n /**\n * Complete passkey registration\n *\n * Completes the WebAuthn registration with the attestation result.\n * Requires authentication.\n *\n * @param data - WebAuthn attestation result and optional passkey name\n * @param options - Optional request options\n * @returns Success response\n */\n async finishPasskeyRegistration(\n data: Types.FinishPasskeyRegistrationRequest,\n options?: RequestOptions\n ): Promise<Types.PasskeyResponse> {\n return this.post<Types.PasskeyResponse>(\n '/passkeys/register/finish',\n data,\n options\n );\n }\n\n /**\n * List registered passkeys\n *\n * Returns all passkeys registered by the authenticated user.\n * Requires authentication.\n *\n * @param options - Optional request options\n * @returns Array of passkey information\n */\n async listPasskeys(\n options?: RequestOptions\n ): Promise<Types.PasskeyResponse[]> {\n const response = await this.get<Types.PasskeysResponse>('/passkeys', options);\n return response.passkeys;\n }\n\n /**\n * Delete a passkey\n *\n * Removes a registered passkey from the authenticated user's account.\n * If the user has TOTP 2FA enabled, a valid TOTP code must be provided.\n * Requires authentication.\n *\n * @param passkeyId - Passkey ID to delete\n * @param data - Optional request body with TOTP code for 2FA verification\n * @param options - Optional request options\n * @returns Success response\n */\n async deletePasskey(\n passkeyId: string,\n data?: Types.DeletePasskeyRequest,\n options?: RequestOptions\n ): Promise<Types.SuccessResponse> {\n return this.delete<Types.SuccessResponse>(\n `/passkeys/${encodeURIComponent(passkeyId)}`,\n data,\n options\n );\n }\n\n // ============================================================================\n // Google OAuth - Public Endpoints\n // ============================================================================\n\n /**\n * Get Google OAuth authorization URL and its CSRF state.\n *\n * Returns `{ url, state }`. Redirect the user to `url`, and keep `state` —\n * `handleGoogleOAuthCallback` requires it. When the client was constructed\n * with an `oauthStateStore`, the state is persisted here automatically.\n *\n * @param params - Query parameters including redirect_uri\n * @param options - Optional request options\n * @returns The authorization URL and the single-use state to round-trip\n */\n async getGoogleOAuthURL(\n params: { redirect_uri: string },\n options?: RequestOptions\n ): Promise<Types.GoogleOAuthURLResponse> {\n const queryParams = new URLSearchParams({ redirect_uri: params.redirect_uri });\n const response = await this.get<Types.GoogleOAuthURLResponse>(\n `/oauth/google/url?${queryParams.toString()}`,\n this.publicOptions(options)\n );\n\n // Persist before the caller redirects. Done here rather than left to the\n // caller because \"remember to store this across a full-page redirect\" is\n // exactly the step whose omission made this flow exploitable.\n if (this.oauthStateStore && response.state) {\n this.oauthStateStore.save(response.state);\n }\n\n return response;\n }\n\n /**\n * Handle Google OAuth callback\n *\n * Exchanges the Google OAuth authorization code for access tokens.\n * Creates a new user if one doesn't exist with the Google email.\n *\n * The `state` from `getGoogleOAuthURL` is **required**: the server validates\n * it before exchanging the code, and rejects a mismatch, absence, expiry or\n * reuse. See {@link Types.GoogleOAuthCallbackRequest.state}.\n *\n * @param data - OAuth callback data: code, redirect_uri and state\n * @param options - Optional request options\n * @returns Access and refresh tokens\n * @throws {MPFValidationError} If `state` is missing or empty (client-side).\n */\n async handleGoogleOAuthCallback(\n data: Types.GoogleOAuthCallbackRequest,\n options?: RequestOptions\n ): Promise<Types.AccessDataResponse> {\n // Fail here rather than sending a request the server must reject. A caller\n // reaching this with no state has lost the pending flow (wrong tab, cleared\n // storage, or a hand-rolled callback that dropped it) and the local error\n // names the cause; a server-side rejection would not.\n if (typeof data.state !== 'string' || data.state === '') {\n throw new MPFValidationError(\n 'OAuth callback requires the `state` returned by getGoogleOAuthURL. ' +\n 'It is the CSRF defence for this flow: without it a callback carrying ' +\n \"an attacker's authorization code would be accepted. Persist it across \" +\n 'the redirect with createOAuthStateStore().',\n { field: 'state' },\n { state: ['state is required'] }\n );\n }\n\n return this.post<Types.AccessDataResponse>(\n '/oauth/google/callback',\n data,\n this.publicOptions(options)\n );\n }\n}\n","import type { MPFRole } from '../auth/claims-types.js';\n\n// NOTE: deliberately NOT re-exported (`export type { MPFRole }`).\n//\n// This module is namespace-re-exported from the root barrel as `AuthTypes`, and\n// tsup's declaration bundler mis-compiles a type re-export in that position: it\n// emitted `declare const types_MPFRole: typeof MPFRole;` — a *value* declaration\n// for a type — which makes the shipped .d.ts fail to compile with\n// `TS2693: 'MPFRole' only refers to a type, but is being used as a value here`.\n//\n// Invisible in this repo because our tsconfig sets `skipLibCheck: true`; a\n// consumer building with `skipLibCheck: false` gets a hard error. Found by\n// typechecking the packed tarball from outside the workspace.\n//\n// `MPFRole` is still exported from the root barrel and from the `/auth` subpath\n// via `src/auth/claims-types.ts`, which is where it belongs.\n\n/**\n * Roles accepted when WRITING a membership (inviting a member, updating a\n * role).\n *\n * Closed on purpose, and only here: on a request, autocomplete earns its keep\n * and an unknown role is a client bug worth catching at compile time.\n *\n * On RESPONSES the role is {@link MPFRole} (= `string`) instead. Roles are\n * database rows (`identity.tenant_membership_valid_roles`), so closing the union\n * on server output means a newly seeded role forces an SDK release — and it is\n * exactly how the fictional `'viewer'` role ended up in these types in five\n * places while the DB actually seeds `guest`.\n */\nexport type MPFTenantRoleInput = 'owner' | 'admin' | 'member' | 'guest';\n\n// ============================================================================\n// Request Types\n// ============================================================================\n\n/**\n * Request body for user registration\n */\nexport interface CreateUserRequest {\n /** User's email address */\n email: string;\n /** User's password (minimum 8 characters) */\n password: string;\n /** User's display name */\n display_name?: string;\n /** User's first name */\n first_name?: string;\n /** User's last name */\n last_name?: string;\n}\n\n/**\n * Request body for user login\n */\nexport interface LoginRequest {\n /** User's email address */\n email: string;\n /** User's password */\n password: string;\n}\n\n/**\n * Request body for profile update\n */\nexport interface UpdateProfileRequest {\n /** User's display name */\n display_name?: string;\n /** User's first name */\n first_name?: string;\n /** User's last name */\n last_name?: string;\n /** Custom user metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Request body for adding an email\n */\nexport interface AddEmailRequest {\n /** Email address to add */\n email: string;\n}\n\n/**\n * Request body for adding a phone number\n */\nexport interface AddPhoneRequest {\n /** Phone number in E.164 format */\n phone_number: string;\n}\n\n/**\n * Request body for verifying email or phone\n */\nexport interface VerifyContactRequest {\n /** 6-digit verification code */\n code: string;\n}\n\n/**\n * Request body for sending password recovery code\n */\nexport interface SendRecoveryCodeRequest {\n /** User's email address */\n email: string;\n}\n\n/**\n * Request body for verifying recovery code\n */\nexport interface VerifyRecoveryCodeRequest {\n /** User's email address */\n email: string;\n /** 6-digit verification code */\n verification_code: string;\n}\n\n/**\n * Request body for password reset\n */\nexport interface ResetPasswordRequest {\n /** Recovery token obtained from verification step */\n recovery_token: string;\n /** New password to set (minimum 8 characters) */\n new_password: string;\n}\n\n/**\n * Request body for authenticated password update\n */\nexport interface UpdatePasswordRequest {\n /** Current password for verification */\n current_password: string;\n /** New password to set (minimum 8 characters) */\n new_password: string;\n}\n\n/**\n * Request body for session renewal\n */\nexport interface RenewSessionRequest {\n /** The refresh token from the current session */\n refresh_token: string;\n}\n\n/**\n * Request body for session revocation\n */\nexport interface RevokeSessionRequest {\n /** The refresh token of the session to revoke */\n refresh_token: string;\n}\n\n/**\n * Request body for tenant creation\n */\nexport interface CreateTenantRequest {\n /** Name of the tenant organization */\n name: string;\n /** URL-friendly slug (auto-generated from name if omitted) */\n slug?: string;\n /** Optional description of the tenant */\n description?: string;\n}\n\n/**\n * Request body for inviting a member\n */\nexport interface InviteMemberRequest {\n /** Email address of the person to invite */\n email: string;\n /** Role to assign to the invited member */\n role: MPFTenantRoleInput;\n /**\n * Optional override for the configured accept URL template. The literal\n * \"{token}\" is replaced with the invitation token.\n */\n accept_url_template?: string;\n}\n\n/**\n * Result of POST /tenants/{id}/members/invite.\n */\nexport interface InvitationResponse {\n invitation_id: string;\n invite_token: string;\n /** Copyable URL the invitee can use; safe fallback if email delivery fails. */\n accept_url: string;\n email: string;\n role: string;\n expires_at: string;\n /** True when no existing user matches the invited email. */\n is_new_user: boolean;\n /** True when the invitation email was successfully dispatched. */\n email_sent: boolean;\n /** Legacy field. Always empty in the new invitation flow. */\n membership_id?: string;\n}\n\n/**\n * Public, pre-auth view of an invitation. Email is intentionally omitted.\n */\nexport interface InvitationPreviewResponse {\n tenant_id: string;\n tenant_name: string;\n tenant_slug?: string;\n role: string;\n inviter_display_name?: string;\n expires_at: string;\n /** True when the invitee has no verified account yet. */\n requires_signup: boolean;\n}\n\n/**\n * Result of POST /invitations/{token}/accept.\n */\nexport interface AcceptInvitationResponse {\n invitation_id: string;\n tenant_id: string;\n role: string;\n membership_id: string;\n accepted_at: string;\n}\n\n/**\n * Request body for updating member role\n */\nexport interface UpdateMemberRoleRequest {\n /** New role for the member */\n role: MPFTenantRoleInput;\n}\n\n// ============================================================================\n// TOTP (Two-Factor Authentication) Types\n// ============================================================================\n\n/**\n * Request body for verifying a TOTP code\n */\nexport interface VerifyTOTPRequest {\n /** 6-digit TOTP code from authenticator app */\n code: string;\n}\n\n/**\n * Request body for disabling TOTP\n */\nexport interface DisableTOTPRequest {\n /** 6-digit TOTP code to confirm disable */\n code: string;\n}\n\n/**\n * Request body for deleting a passkey (optional, required when user has TOTP 2FA enabled)\n */\nexport interface DeletePasskeyRequest {\n /** 6-digit TOTP code from authenticator app */\n totp_code?: string;\n}\n\n// ============================================================================\n// Passkey / WebAuthn Types\n// ============================================================================\n\n/** WebAuthn credential descriptor as serialized by the API */\nexport interface WebAuthnCredentialDescriptor {\n type: string;\n id: string;\n transports?: string[];\n}\n\n/** WebAuthn creation options as serialized by the API (base64url strings, not ArrayBuffers) */\nexport interface WebAuthnCreationOptions {\n rp: { id: string; name: string };\n user: { id: string; name: string; displayName: string };\n challenge: string;\n pubKeyCredParams: Array<{ type: string; alg: number }>;\n timeout?: number;\n excludeCredentials?: WebAuthnCredentialDescriptor[];\n authenticatorSelection?: {\n authenticatorAttachment?: string;\n residentKey?: string;\n requireResidentKey?: boolean;\n userVerification?: string;\n };\n attestation?: string;\n hints?: string[];\n extensions?: Record<string, unknown>;\n}\n\n/** WebAuthn request options as serialized by the API (base64url strings, not ArrayBuffers) */\nexport interface WebAuthnRequestOptions {\n challenge: string;\n rpId?: string;\n timeout?: number;\n allowCredentials?: WebAuthnCredentialDescriptor[];\n userVerification?: string;\n hints?: string[];\n extensions?: Record<string, unknown>;\n}\n\n/** Encoded credential sent back to the server after navigator.credentials.create/get */\nexport interface WebAuthnEncodedCredential {\n id: string;\n rawId: string;\n type: string;\n response: {\n clientDataJSON: string;\n attestationObject?: string;\n authenticatorData?: string;\n signature?: string;\n userHandle?: string | null;\n };\n}\n\n/**\n * Request body for completing passkey registration\n */\nexport interface FinishPasskeyRegistrationRequest {\n /** Raw WebAuthn credential from navigator.credentials.create() */\n credential: WebAuthnEncodedCredential;\n /** Optional human-readable name for the passkey */\n name?: string;\n}\n\n/**\n * Request body for completing passkey login\n */\nexport interface FinishPasskeyLoginRequest {\n /** Raw WebAuthn credential from navigator.credentials.get() */\n credential: WebAuthnEncodedCredential;\n /** Session key returned from begin login */\n session_key: string;\n}\n\n// ============================================================================\n// Google OAuth Types\n// ============================================================================\n\n/**\n * Request body for Google OAuth callback\n */\nexport interface GoogleOAuthCallbackRequest {\n /** Authorization code from Google */\n code: string;\n /** Redirect URI used in the initial auth request */\n redirect_uri: string;\n /**\n * The `state` returned by `getGoogleOAuthURL`, round-tripped through the\n * redirect.\n *\n * **Required, and required for a reason.** It is the CSRF defence for this\n * flow: the server validates it before exchanging the code, so a callback\n * carrying an attacker's `code` but not the victim's `state` is rejected.\n * Without it, an attacker can sign a victim into the attacker's own account —\n * confirmed exploitable, not hypothetical.\n *\n * Persist it across the redirect with `createOAuthStateStore()` (web storage:\n * a full-page redirect discards anything held in memory).\n */\n state: string;\n}\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\n/**\n * Response containing access and refresh tokens\n */\nexport interface AccessDataResponse {\n /** JWT access token for API authentication */\n access_token: string;\n /** Refresh token for session renewal */\n refresh_token: string;\n}\n\n/**\n * User profile information\n */\nexport interface UserProfileResponse {\n /** User's unique identifier */\n id: string;\n /** User's display name */\n display_name?: string;\n /** User's first name */\n first_name?: string;\n /** User's last name */\n last_name?: string;\n /** User's avatar URL */\n avatar_url?: string;\n /** User's email addresses */\n emails: EmailResponse[];\n /** User's phone numbers */\n phones: PhoneResponse[];\n}\n\n/**\n * Email address information\n */\nexport interface EmailResponse {\n /** Email's unique identifier */\n id: string;\n /** Email address */\n email: string;\n /** Whether this is the primary email */\n is_primary: boolean;\n /** When the email was verified (ISO 8601), undefined if not verified */\n verified_at?: string;\n}\n\n/**\n * Phone number information\n */\nexport interface PhoneResponse {\n /** Phone's unique identifier */\n id: string;\n /** Phone number in E.164 format */\n phone_number: string;\n /** Whether this is the primary phone */\n is_primary: boolean;\n /** When the phone was verified (ISO 8601), undefined if not verified */\n verified_at?: string;\n}\n\n/**\n * Session client information\n */\nexport interface SessionClientInfo {\n /** Client name */\n name?: string;\n /** Client user agent string */\n user_agent?: string;\n /** Client IP address */\n ip_address?: string;\n /** When the client was last seen (ISO 8601) */\n last_seen_at?: string;\n}\n\n/**\n * Session information\n */\nexport interface SessionResponse {\n /** Session's unique identifier */\n id: string;\n /** Client ID associated with the session */\n client_id: string;\n /** Client information */\n client?: SessionClientInfo;\n /** When the session expires (ISO 8601) */\n expires_at: string;\n /** When the session was created (ISO 8601) */\n created_at: string;\n /** Whether this is the current session */\n is_current: boolean;\n}\n\n/**\n * OAuth client information\n */\nexport interface ClientResponse {\n /** Client's unique identifier */\n id: string;\n /** Client name */\n name?: string;\n /** Client user agent string */\n user_agent?: string;\n /** Client IP address */\n ip_address?: string;\n /** When the client was last seen (ISO 8601) */\n last_seen_at?: string;\n}\n\n/**\n * Tenant information\n */\nexport interface TenantResponse {\n /** Tenant's unique identifier */\n id: string;\n /** Tenant name */\n name: string;\n /** Tenant description */\n description?: string;\n /** Tenant slug (URL-friendly identifier) */\n slug?: string;\n /** When the tenant was created (ISO 8601) */\n created_at: string;\n}\n\n/**\n * Tenant membership information\n */\nexport interface MembershipResponse {\n /** Membership unique identifier */\n id: string;\n /** User's unique identifier */\n user_id: string;\n /** Member's role in the tenant */\n role: MPFRole;\n /** When the member was invited (ISO 8601) */\n invited_at?: string;\n /** When the invitation was accepted (ISO 8601) */\n accepted_at?: string;\n /** Member's display name */\n display_name?: string;\n /** Member's email address */\n email?: string;\n}\n\n/**\n * Response containing recovery token\n */\nexport interface RecoveryTokenResponse {\n /** Token to use for password reset */\n recovery_token: string;\n}\n\n/**\n * Simple success response\n */\nexport interface SuccessResponse {\n /** Indicates if the operation was successful */\n success: boolean;\n}\n\n/**\n * Error response from the API\n */\nexport interface ErrorResponse {\n /** Human-readable error message */\n error: string;\n /** Machine-readable error code */\n code?: string;\n /** Additional error details (validation errors, etc.) */\n details?: unknown;\n}\n\n/**\n * Validation error detail for a specific field\n */\nexport interface ValidationErrorDetail {\n /** Name of the field with validation error */\n field: string;\n /** Validation error message */\n message: string;\n}\n\n/**\n * Service health status response\n */\nexport interface HealthResponse {\n /** Health status */\n status: string;\n /** Service name */\n service: string;\n /** Current server timestamp (ISO 8601) */\n timestamp: string;\n}\n\n// ============================================================================\n// TOTP Response Types\n// ============================================================================\n\n/**\n * Response from TOTP setup containing secret and backup codes\n */\nexport interface TOTPSetupResponse {\n /** TOTP secret key for manual entry */\n secret: string;\n /** otpauth:// URL for QR code generation */\n qr_url: string;\n /** One-time backup codes for account recovery */\n backup_codes: string[];\n}\n\n// ============================================================================\n// Passkey Response Types\n// ============================================================================\n\n/**\n * Response from begin passkey registration\n */\nexport interface BeginPasskeyRegistrationResponse {\n /** WebAuthn PublicKeyCredentialCreationOptions */\n options: WebAuthnCreationOptions;\n}\n\n/**\n * Response from begin passkey login\n */\nexport interface BeginPasskeyLoginResponse {\n /** WebAuthn PublicKeyCredentialRequestOptions */\n options: WebAuthnRequestOptions;\n /** Session key to pass back in finish login */\n session_key: string;\n}\n\n/**\n * Passkey credential information\n */\nexport interface PasskeyResponse {\n /** Passkey's unique identifier */\n id: string;\n /** Human-readable name for the passkey */\n name?: string;\n /** When the passkey was registered (ISO 8601) */\n created_at: string;\n /** When the passkey was last used (ISO 8601) */\n last_used_at?: string;\n}\n\n// ============================================================================\n// OAuth Response Types\n// ============================================================================\n\n/**\n * A pending invitation for the current user\n */\nexport interface PendingInvitationResponse {\n /** Invitation/membership ID */\n id: string;\n /** Tenant ID the invitation is for */\n tenant_id: string;\n /** Tenant name */\n tenant_name: string;\n /** Tenant slug */\n tenant_slug?: string;\n /** Role assigned in the invitation */\n role: MPFRole;\n /** User ID of the person who sent the invitation */\n invited_by: string;\n /** When the invitation was sent (ISO 8601) */\n invited_at: string;\n /** Invitation token for accepting */\n token: string;\n}\n\n/**\n * A pending invitation issued by the authenticated caller, returned by\n * GET /tenants/{id}/invitations.\n */\nexport interface IssuedInvitationResponse {\n /** Invitation ID */\n id: string;\n /** Tenant the invitation was issued for */\n tenant_id: string;\n /** Email the invitation was sent to */\n email: string;\n /** Role the invitee will receive on accept */\n role: MPFRole;\n /** User ID of the inviter (always the authenticated caller) */\n invited_by: string;\n /** When the invitation was sent (ISO 8601) */\n invited_at: string;\n /** Expiration time (ISO 8601) */\n expires_at: string;\n /** Raw token. Most callers should use accept_url instead. */\n token: string;\n /**\n * Copyable URL the invitee can paste into a browser. Empty if the server\n * has no accept-URL template configured.\n */\n accept_url: string;\n /** Display name of the invitee, if they already have an account */\n display_name?: string;\n}\n\n/**\n * Response containing Google OAuth authorization URL\n */\nexport interface GoogleOAuthURLResponse {\n /** Full Google OAuth authorization URL to redirect user to */\n url: string;\n /**\n * Single-use CSRF state minted and recorded by the server.\n *\n * Persist this before redirecting and send it back on\n * `handleGoogleOAuthCallback`. Dropping it makes the callback trivially\n * forgeable — see {@link GoogleOAuthCallbackRequest.state}.\n */\n state: string;\n}\n\n// ============================================================================\n// List Wrapper Response Types\n// ============================================================================\n\n/**\n * Wrapper response for email list\n */\nexport interface EmailsResponse {\n emails: EmailResponse[];\n}\n\n/**\n * Wrapper response for phone list\n */\nexport interface PhonesResponse {\n phones: PhoneResponse[];\n}\n\n/**\n * Wrapper response for session list\n */\nexport interface SessionsResponse {\n sessions: SessionResponse[];\n}\n\n/**\n * Wrapper response for passkey list\n */\nexport interface PasskeysResponse {\n passkeys: PasskeyResponse[];\n}\n\n/**\n * Wrapper response for client list\n */\nexport interface ClientsResponse {\n clients: ClientResponse[];\n}\n\n/**\n * Wrapper response for member list\n */\nexport interface MembersResponse {\n members: MembershipResponse[];\n}\n\n/**\n * Wrapper response for pending-invitations-issued-by-caller list\n */\nexport interface IssuedInvitationsResponse {\n invitations: IssuedInvitationResponse[];\n}\n\n// ============================================================================\n// MFA Response Types\n// ============================================================================\n\n/**\n * Returned when MFA verification is needed to complete login\n */\nexport interface MFARequiredResponse {\n /** Always true for this response type */\n mfa_required: true;\n /** Short-lived JWT ticket for MFA verification */\n mfa_ticket: string;\n /** Available MFA methods (e.g., [\"totp\"]) */\n mfa_methods: string[];\n}\n\n/**\n * Returned when MFA setup is enforced and user hasn't set up TOTP yet\n */\nexport interface MFASetupRequiredResponse {\n /** Always true for this response type */\n mfa_setup_required: true;\n /** Short-lived JWT ticket for MFA setup verification */\n mfa_ticket: string;\n /** TOTP setup data including secret and QR code */\n totp_setup: TOTPSetupResponse;\n}\n\n/**\n * Union type for all possible login responses\n */\nexport type LoginResponse = AccessDataResponse | MFARequiredResponse | MFASetupRequiredResponse;\n\n/**\n * Type guard to check if login response requires MFA verification\n */\nexport function isMFARequired(response: LoginResponse): response is MFARequiredResponse {\n return 'mfa_required' in response && response.mfa_required === true;\n}\n\n/**\n * Type guard to check if login response requires MFA setup\n */\nexport function isMFASetupRequired(response: LoginResponse): response is MFASetupRequiredResponse {\n return 'mfa_setup_required' in response && response.mfa_setup_required === true;\n}\n\n// ============================================================================\n// MFA Request Types\n// ============================================================================\n\n/**\n * Request body for verifying MFA during login\n */\nexport interface MFAVerifyRequest {\n /** MFA ticket from login response */\n mfa_ticket: string;\n /** 6-digit TOTP code from authenticator app */\n totp_code: string;\n}\n\n/**\n * Request body for verifying MFA setup during first-time enrollment\n */\nexport interface MFASetupVerifyRequest {\n /** MFA ticket from login response */\n mfa_ticket: string;\n /** 6-digit TOTP code to verify setup */\n code: string;\n}\n"]}
@@ -406,5 +406,5 @@ function tokenLifetimeSeconds(claims) {
406
406
  }
407
407
 
408
408
  export { DeadSessionError, MPFAPIError, MPFAuthError, MPFClaimsError, MPFError, MPFNetworkError, MPFTimeoutError, MPFUnsupportedClaimsVersionError, MPFValidationError, __export, canSelect, clearClaimsCache, decodeAccessToken, defaultRoleForTenant, expiresAt, isDeadSession, isExpired, isMPFAPIError, isMPFAuthError, isMPFError, isMPFNetworkError, isMPFValidationError, listTenants, registerClaimsParser, rolesForTenant, supportedClaimsVersions, tokenLifetimeSeconds, tryDecodeAccessToken };
409
- //# sourceMappingURL=chunk-AJWM5MDZ.js.map
410
- //# sourceMappingURL=chunk-AJWM5MDZ.js.map
409
+ //# sourceMappingURL=chunk-S5DKGPUY.js.map
410
+ //# sourceMappingURL=chunk-S5DKGPUY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/core/errors.ts","../src/auth/errors.ts","../src/auth/claims.ts"],"names":[],"mappings":";;;;;;;;;AAOO,IAAM,QAAA,GAAN,cAAuB,KAAA,CAAM;AAAA;AAAA,EAEzB,IAAA;AAAA;AAAA,EAEA,MAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,IAAA,EAAc,MAAA,EAAiB,OAAA,EAAmB;AAC7E,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,UAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAGf,IAAA,IAAI,MAAM,iBAAA,EAAmB;AAC3B,MAAA,KAAA,CAAM,iBAAA,CAAkB,IAAA,EAAM,IAAA,CAAK,WAAW,CAAA;AAAA,IAChD;AAGA,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAA,GAAkC;AAChC,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,EACF;AACF;AAKO,IAAM,eAAA,GAAN,cAA8B,QAAA,CAAS;AAAA;AAAA,EAEnC,KAAA;AAAA,EAET,WAAA,CAAY,SAAiB,KAAA,EAAe;AAC1C,IAAA,KAAA,CAAM,SAAS,eAAe,CAAA;AAC9B,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AAEb,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO;AAAA,MACL,GAAG,MAAM,MAAA,EAAO;AAAA,MAChB,KAAA,EAAO,KAAK,KAAA,EAAO;AAAA,KACrB;AAAA,EACF;AACF;AAKO,IAAM,WAAA,GAAN,cAA0B,QAAA,CAAS;AAAA;AAAA,EAE/B,IAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,IAAA,EAAc,MAAA,EAAgB,SAAmB,IAAA,EAAgB;AAC5F,IAAA,KAAA,CAAM,OAAA,EAAS,IAAA,EAAM,MAAA,EAAQ,OAAO,CAAA;AACpC,IAAA,IAAA,CAAK,IAAA,GAAO,aAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAEZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO;AAAA,MACL,GAAG,MAAM,MAAA,EAAO;AAAA,MAChB,MAAM,IAAA,CAAK;AAAA,KACb;AAAA,EACF;AACF;AAKO,IAAM,kBAAA,GAAN,cAAiC,QAAA,CAAS;AAAA;AAAA,EAEtC,WAAA;AAAA,EAET,WAAA,CAAY,OAAA,EAAiB,OAAA,EAAmB,WAAA,EAAwC;AACtF,IAAA,KAAA,CAAM,OAAA,EAAS,kBAAA,EAAoB,GAAA,EAAK,OAAO,CAAA;AAC/C,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AACZ,IAAA,IAAA,CAAK,WAAA,GAAc,WAAA;AAEnB,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO;AAAA,MACL,GAAG,MAAM,MAAA,EAAO;AAAA,MAChB,aAAa,IAAA,CAAK;AAAA,KACpB;AAAA,EACF;AACF;AAKO,IAAM,YAAA,GAAN,cAA2B,QAAA,CAAS;AAAA;AAAA,EAEhC,aAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,UAAA;AAAA,EAET,YACE,OAAA,EACA,aAAA,EACA,MAAA,GAAoB,GAAA,EACpB,SACA,UAAA,EACA;AACA,IAAA,MAAM,IAAA,GAAO,cAAc,WAAA,EAAY;AACvC,IAAA,KAAA,CAAM,OAAA,EAAS,IAAA,EAAM,MAAA,EAAQ,OAAO,CAAA;AACpC,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AACZ,IAAA,IAAA,CAAK,aAAA,GAAgB,aAAA;AACrB,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAElB,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA;AAAA;AAAA;AAAA,EAKA,cAAA,GAA0B;AACxB,IAAA,OAAO,KAAK,aAAA,KAAkB,eAAA;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA,EAKA,WAAA,GAAuB;AACrB,IAAA,OAAO,KAAK,aAAA,KAAkB,WAAA;AAAA,EAChC;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO;AAAA,MACL,GAAG,MAAM,MAAA,EAAO;AAAA,MAChB,eAAe,IAAA,CAAK,aAAA;AAAA,MACpB,YAAY,IAAA,CAAK;AAAA,KACnB;AAAA,EACF;AACF;AAKO,IAAM,eAAA,GAAN,cAA8B,QAAA,CAAS;AAAA;AAAA,EAEnC,SAAA;AAAA,EAET,WAAA,CAAY,SAAiB,SAAA,EAAmB;AAC9C,IAAA,KAAA,CAAM,SAAS,eAAe,CAAA;AAC9B,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,SAAA,GAAY,SAAA;AAEjB,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO;AAAA,MACL,GAAG,MAAM,MAAA,EAAO;AAAA,MAChB,WAAW,IAAA,CAAK;AAAA,KAClB;AAAA,EACF;AACF;AAKO,SAAS,WAAW,KAAA,EAAmC;AAC5D,EAAA,OAAO,KAAA,YAAiB,QAAA;AAC1B;AAKO,SAAS,eAAe,KAAA,EAAuC;AACpE,EAAA,OAAO,KAAA,YAAiB,YAAA;AAC1B;AAKO,SAAS,cAAc,KAAA,EAAsC;AAClE,EAAA,OAAO,KAAA,YAAiB,WAAA;AAC1B;AAKO,SAAS,kBAAkB,KAAA,EAA0C;AAC1E,EAAA,OAAO,KAAA,YAAiB,eAAA;AAC1B;AAKO,SAAS,qBAAqB,KAAA,EAA6C;AAChF,EAAA,OAAO,KAAA,YAAiB,kBAAA;AAC1B;;;AC7NO,IAAM,cAAA,GAAN,cAA6B,QAAA,CAAS;AAAA,EAC3C,WAAA,CAAY,OAAA,EAAiB,IAAA,GAAO,gBAAA,EAAkB,OAAA,EAAmB;AACvE,IAAA,KAAA,CAAM,OAAA,EAAS,IAAA,EAAM,MAAA,EAAW,OAAO,CAAA;AACvC,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AACZ,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AACF;AASO,IAAM,gCAAA,GAAN,cAA+C,cAAA,CAAe;AAAA;AAAA,EAE1D,OAAA;AAAA,EAET,YAAY,OAAA,EAAwB;AAClC,IAAA,KAAA;AAAA,MACE,OAAA,KAAY,IAAA,GACR,0CAAA,GACA,CAAA,yCAAA,EAA4C,OAAO,CAAA,CAAA;AAAA,MACvD,4BAAA;AAAA,MACA,EAAE,OAAA;AAAQ,KACZ;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,kCAAA;AACZ,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AACf,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO,EAAE,GAAG,KAAA,CAAM,QAAO,EAAG,OAAA,EAAS,KAAK,OAAA,EAAQ;AAAA,EACpD;AACF;AASO,IAAM,gBAAA,GAAN,cAA+B,QAAA,CAAS;AAAA;AAAA,EAEpC,KAAA;AAAA,EAET,WAAA,CAAY,OAAA,GAAU,4BAAA,EAA8B,KAAA,EAAe;AACjE,IAAA,KAAA,CAAM,OAAA,EAAS,gBAAgB,GAAG,CAAA;AAClC,IAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AACZ,IAAA,IAAA,CAAK,KAAA,GAAQ,KAAA;AACb,IAAA,MAAA,CAAO,cAAA,CAAe,IAAA,EAAM,GAAA,CAAA,MAAA,CAAW,SAAS,CAAA;AAAA,EAClD;AAAA,EAES,MAAA,GAAkC;AACzC,IAAA,OAAO,EAAE,GAAG,KAAA,CAAM,MAAA,IAAU,KAAA,EAAO,IAAA,CAAK,OAAO,OAAA,EAAQ;AAAA,EACzD;AACF;AAKO,SAAS,cAAc,KAAA,EAA2C;AACvE,EAAA,OAAO,KAAA,YAAiB,gBAAA;AAC1B;AC/BA,IAAM,gBAAA,GAAmB,CAAA;AAYzB,IAAM,WAAA,uBAAkB,GAAA,EAAuB;AAE/C,SAAS,SAAS,KAAA,EAAsC;AACtD,EAAA,MAAM,GAAA,GAAM,WAAA,CAAY,GAAA,CAAI,KAAK,CAAA;AACjC,EAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,WAAA,CAAY,OAAO,KAAK,CAAA;AACxB,EAAA,WAAA,CAAY,GAAA,CAAI,OAAO,GAAG,CAAA;AAC1B,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,QAAA,CAAS,OAAe,MAAA,EAAyB;AACxD,EAAA,IAAI,WAAA,CAAY,GAAA,CAAI,KAAK,CAAA,EAAG;AAC1B,IAAA,WAAA,CAAY,OAAO,KAAK,CAAA;AAAA,EAC1B;AACA,EAAA,WAAA,CAAY,GAAA,CAAI,OAAO,MAAM,CAAA;AAE7B,EAAA,OAAO,WAAA,CAAY,OAAO,gBAAA,EAAkB;AAC1C,IAAA,MAAM,MAAA,GAAS,WAAA,CAAY,IAAA,EAAK,CAAE,IAAA,EAAK;AACvC,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA;AAAA,IACF;AACA,IAAA,WAAA,CAAY,MAAA,CAAO,OAAO,KAAK,CAAA;AAAA,EACjC;AACF;AAOO,SAAS,gBAAA,GAAyB;AACvC,EAAA,WAAA,CAAY,KAAA,EAAM;AACpB;AAMA,SAAS,aAAA,CAAc,SAAkC,GAAA,EAAqB;AAC5E,EAAA,MAAM,KAAA,GAAQ,QAAQ,GAAG,CAAA;AACzB,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,WAAW,CAAA,EAAG;AACnD,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,OAAA,EAAU,GAAG,CAAA,4BAAA,CAA8B,CAAA;AAAA,EACtE;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,aAAA,CAAc,SAAkC,GAAA,EAAqB;AAC5E,EAAA,MAAM,KAAA,GAAQ,QAAQ,GAAG,CAAA;AACzB,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AACxD,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,OAAA,EAAU,GAAG,CAAA,yBAAA,CAA2B,CAAA;AAAA,EACnE;AACA,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,cAAA,CAAe,SAAkC,GAAA,EAAiC;AACzF,EAAA,MAAM,KAAA,GAAQ,QAAQ,GAAG,CAAA;AACzB,EAAA,IAAI,UAAU,MAAA,EAAW;AACvB,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AACxD,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,OAAA,EAAU,GAAG,CAAA,sCAAA,CAAwC,CAAA;AAAA,EAChF;AACA,EAAA,OAAO,KAAA;AACT;AAaA,SAAS,cAAA,CAAe,SAAkC,GAAA,EAAiC;AACzF,EAAA,MAAM,KAAA,GAAQ,QAAQ,GAAG,CAAA;AACzB,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,IAAQ,UAAU,EAAA,EAAI;AACzD,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,OAAA,EAAU,GAAG,CAAA,+BAAA,CAAiC,CAAA;AAAA,EACzE;AACA,EAAA,OAAO,KAAA;AACT;AAeA,SAAS,kBAAkB,OAAA,EAAoD;AAC7E,EAAA,MAAM,KAAA,GAAQ,QAAQ,MAAM,CAAA;AAG5B,EAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACzB,IAAA,MAAM,IAAI,eAAe,4CAA4C,CAAA;AAAA,EACvE;AAEA,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,KAAA,EAAO,CAAA,KAAM;AAC7B,IAAA,IAAI,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACvE,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,YAAA,EAAe,CAAC,CAAA,oBAAA,CAAsB,CAAA;AAAA,IACjE;AACA,IAAA,MAAM,MAAA,GAAS,KAAA;AAEf,IAAA,MAAM,EAAA,GAAK,OAAO,IAAI,CAAA;AACtB,IAAA,IAAI,OAAO,EAAA,KAAO,QAAA,IAAY,EAAA,CAAG,WAAW,CAAA,EAAG;AAC7C,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,YAAA,EAAe,CAAC,CAAA,gCAAA,CAAkC,CAAA;AAAA,IAC7E;AAEA,IAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AACxB,IAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,IAAK,GAAA,CAAI,IAAA,CAAK,CAAC,IAAA,KAAS,OAAO,IAAA,KAAS,QAAQ,CAAA,EAAG;AACvE,MAAA,MAAM,IAAI,cAAA,CAAe,CAAA,YAAA,EAAe,CAAC,CAAA,kCAAA,CAAoC,CAAA;AAAA,IAC/E;AAEA,IAAA,MAAM,SAAyB,EAAE,EAAA,EAAI,KAAK,CAAC,GAAI,GAAiB,CAAA,EAAE;AAKlE,IAAA,MAAM,GAAA,GAAM,OAAO,KAAK,CAAA;AACxB,IAAA,IAAI,GAAA,KAAQ,MAAA,IAAa,GAAA,KAAQ,IAAA,IAAQ,QAAQ,EAAA,EAAI;AACnD,MAAA,IAAI,OAAO,QAAQ,QAAA,EAAU;AAC3B,QAAA,MAAM,IAAI,cAAA,CAAe,CAAA,YAAA,EAAe,CAAC,CAAA,oCAAA,CAAsC,CAAA;AAAA,MACjF;AACA,MAAA,MAAA,CAAO,GAAA,GAAM,GAAA;AAAA,IACf;AAEA,IAAA,OAAO,MAAA;AAAA,EACT,CAAC,CAAA;AACH;AAGA,SAAS,UAAA,CAAW,QAAmB,QAAA,EAA8C;AACnF,EAAA,OAAO,OAAO,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,QAAQ,CAAA;AAClD;AAaA,IAAM,OAAA,GAAwB,CAAC,OAAA,KAAY;AAkBzC,EAAA,MAAM,MAAA,GAAsB;AAAA,IAC1B,CAAA,EAAG,CAAA;AAAA,IACH,GAAA,EAAK,aAAA,CAAc,OAAA,EAAS,KAAK,CAAA;AAAA,IACjC,GAAA,EAAK,aAAA,CAAc,OAAA,EAAS,KAAK,CAAA;AAAA,IACjC,GAAA,EAAK,aAAA,CAAc,OAAA,EAAS,KAAK,CAAA;AAAA,IACjC,IAAA,EAAM,kBAAkB,OAAO;AAAA,GACjC;AAEA,EAAA,MAAM,GAAA,GAAM,cAAA,CAAe,OAAA,EAAS,KAAK,CAAA;AACzC,EAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,IAAA,MAAA,CAAO,GAAA,GAAM,GAAA;AAAA,EACf;AAEA,EAAA,MAAM,GAAA,GAAM,cAAA,CAAe,OAAA,EAAS,KAAK,CAAA;AACzC,EAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,IAAA,MAAA,CAAO,GAAA,GAAM,GAAA;AAAA,EACf;AAEA,EAAA,OAAO,MAAA;AACT,CAAA;AAMA,IAAM,OAAA,uBAAc,GAAA,CAA0B,CAAC,CAAC,CAAA,EAAG,OAAO,CAAC,CAAC,CAAA;AAWrD,SAAS,oBAAA,CAAqB,SAAiB,MAAA,EAA4B;AAChF,EAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,OAAO,CAAA,EAAG;AACxB,IAAA,MAAM,IAAI,cAAA,CAAe,CAAA,kDAAA,EAAqD,OAAO,CAAA,CAAE,CAAA;AAAA,EACzF;AACA,EAAA,OAAA,CAAQ,GAAA,CAAI,SAAS,MAAM,CAAA;AAC7B;AAKO,SAAS,uBAAA,GAAoC;AAClD,EAAA,OAAO,CAAC,GAAG,OAAA,CAAQ,IAAA,EAAM,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,CAAA,GAAI,CAAC,CAAA;AACjD;AAoBO,SAAS,kBAAkB,KAAA,EAA0B;AAC1D,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,CAAM,WAAW,CAAA,EAAG;AACnD,IAAA,MAAM,IAAI,eAAe,yCAAyC,CAAA;AAAA,EACpE;AAEA,EAAA,MAAM,MAAA,GAAS,SAAS,KAAK,CAAA;AAC7B,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,UAAU,KAAK,CAAA;AAAA,EAC3B,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,cAAA;AAAA,MACR,CAAA,qCAAA,EAAwC,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,UAAU,eAAe,CAAA,CAAA;AAAA,MAChG;AAAA,KACF;AAAA,EACF;AAEA,EAAA,MAAM,UAAA,GAAa,QAAQ,GAAG,CAAA;AAC9B,EAAA,IAAI,OAAO,UAAA,KAAe,QAAA,IAAY,CAAC,MAAA,CAAO,QAAA,CAAS,UAAU,CAAA,EAAG;AAClE,IAAA,MAAM,IAAI,iCAAiC,IAAI,CAAA;AAAA,EACjD;AAEA,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA;AACrC,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,iCAAiC,UAAU,CAAA;AAAA,EACvD;AAEA,EAAA,MAAM,MAAA,GAAS,OAAO,OAAO,CAAA;AAC7B,EAAA,QAAA,CAAS,OAAO,MAAM,CAAA;AACtB,EAAA,OAAO,MAAA;AACT;AASO,SAAS,qBAAqB,KAAA,EAAoD;AACvF,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,IAAa,UAAU,EAAA,EAAI;AACzD,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,IAAI;AACF,IAAA,OAAO,kBAAkB,KAAK,CAAA;AAAA,EAChC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AASO,SAAS,YAAY,MAAA,EAA6B;AACvD,EAAA,OAAO,OAAO,IAAA,CAAK,GAAA,CAAI,CAAC,MAAA,KAAW,OAAO,EAAE,CAAA;AAC9C;AAOO,SAAS,cAAA,CAAe,QAAmB,QAAA,EAA6B;AAC7E,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,MAAA,EAAQ,QAAQ,CAAA;AAC1C,EAAA,OAAO,SAAS,CAAC,GAAG,MAAA,CAAO,GAAG,IAAI,EAAC;AACrC;AAQO,SAAS,oBAAA,CAAqB,QAAmB,QAAA,EAAuC;AAC7F,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,MAAA,EAAQ,QAAQ,CAAA;AAC1C,EAAA,IAAI,WAAW,MAAA,EAAW;AACxB,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,OAAO,MAAA,CAAO,GAAA,IAAO,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA;AACnC;AAgBO,SAAS,SAAA,CACd,MAAA,EACA,QAAA,EACA,IAAA,EACS;AAET,EAAA,IAAI,aAAa,IAAA,EAAM;AACrB,IAAA,OAAO,IAAA,KAAS,MAAA,IAAa,IAAA,KAAS,MAAA,CAAO,GAAA;AAAA,EAC/C;AAEA,EAAA,MAAM,MAAA,GAAS,UAAA,CAAW,MAAA,EAAQ,QAAQ,CAAA;AAC1C,EAAA,IAAI,CAAC,MAAA,IAAU,MAAA,CAAO,GAAA,CAAI,WAAW,CAAA,EAAG;AACtC,IAAA,OAAO,KAAA;AAAA,EACT;AAIA,EAAA,OAAO,IAAA,KAAS,MAAA,IAAa,MAAA,CAAO,GAAA,CAAI,SAAS,IAAI,CAAA;AACvD;AAKO,SAAS,UAAU,MAAA,EAAyB;AACjD,EAAA,OAAO,IAAI,IAAA,CAAK,MAAA,CAAO,GAAA,GAAM,GAAI,CAAA;AACnC;AAWO,SAAS,SAAA,CAAU,MAAA,EAAmB,WAAA,GAAc,CAAA,EAAG,KAAA,EAAyB;AACrF,EAAA,MAAM,GAAA,GAAA,CAAO,KAAA,IAAS,IAAA,CAAK,GAAA,EAAI,IAAK,GAAA;AACpC,EAAA,OAAO,MAAA,CAAO,MAAM,WAAA,IAAe,GAAA;AACrC;AAMO,SAAS,qBAAqB,MAAA,EAAuC;AAC1E,EAAA,IAAI,MAAA,CAAO,QAAQ,MAAA,EAAW;AAC5B,IAAA,OAAO,MAAA;AAAA,EACT;AACA,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,GAAA,GAAM,MAAA,CAAO,GAAA;AACrC,EAAA,OAAO,QAAA,GAAW,IAAI,QAAA,GAAW,MAAA;AACnC","file":"chunk-AJWM5MDZ.js","sourcesContent":["/**\n * Custom error classes for the MPF SDK\n */\n\n/**\n * Base error class for all MPF SDK errors\n */\nexport class MPFError extends Error {\n /** Machine-readable error code */\n readonly code: string;\n /** HTTP status code if applicable */\n readonly status?: number;\n /** Additional error details from the API */\n readonly details?: unknown;\n\n constructor(message: string, code: string, status?: number, details?: unknown) {\n super(message);\n this.name = 'MPFError';\n this.code = code;\n this.status = status;\n this.details = details;\n\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n\n // Ensure prototype chain is properly set for instanceof checks\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n /**\n * Convert error to a plain object for logging/serialization\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n details: this.details,\n };\n }\n}\n\n/**\n * Error thrown when a network request fails (e.g., no connection, DNS failure)\n */\nexport class MPFNetworkError extends MPFError {\n /** The original error that caused the network failure */\n readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message, 'NETWORK_ERROR');\n this.name = 'MPFNetworkError';\n this.cause = cause;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n cause: this.cause?.message,\n };\n }\n}\n\n/**\n * Error thrown when the API returns an error response\n */\nexport class MPFAPIError extends MPFError {\n /** The raw response body if available */\n readonly body?: unknown;\n\n constructor(message: string, code: string, status: number, details?: unknown, body?: unknown) {\n super(message, code, status, details);\n this.name = 'MPFAPIError';\n this.body = body;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n body: this.body,\n };\n }\n}\n\n/**\n * Error thrown when request validation fails (e.g., invalid parameters)\n */\nexport class MPFValidationError extends MPFError {\n /** Field-specific validation errors */\n readonly fieldErrors?: Record<string, string[]>;\n\n constructor(message: string, details?: unknown, fieldErrors?: Record<string, string[]>) {\n super(message, 'VALIDATION_ERROR', 400, details);\n this.name = 'MPFValidationError';\n this.fieldErrors = fieldErrors;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n fieldErrors: this.fieldErrors,\n };\n }\n}\n\n/**\n * Error thrown when authentication or authorization fails (401/403)\n */\nexport class MPFAuthError extends MPFError {\n /** The type of auth error (e.g., 'unauthorized', 'forbidden', 'token_expired') */\n readonly authErrorType: 'unauthorized' | 'forbidden' | 'token_expired' | 'invalid_token';\n\n /**\n * The machine-readable code the server actually sent, when it sent one.\n *\n * `code` is derived from {@link authErrorType} and therefore collapses every\n * 401 to `UNAUTHORIZED`, which loses information the server deliberately\n * provides — `REFRESH_TOKEN_SUPERSEDED` being the case that matters: it means\n * \"another tab renewed first\", which is recoverable by adopting that tab's\n * token, and must not be treated as a dead session.\n *\n * Kept as a separate field rather than overwriting `code` so that existing\n * consumers switching on `code` are unaffected.\n */\n readonly serverCode?: string;\n\n constructor(\n message: string,\n authErrorType: 'unauthorized' | 'forbidden' | 'token_expired' | 'invalid_token',\n status: 401 | 403 = 401,\n details?: unknown,\n serverCode?: string\n ) {\n const code = authErrorType.toUpperCase();\n super(message, code, status, details);\n this.name = 'MPFAuthError';\n this.authErrorType = authErrorType;\n this.serverCode = serverCode;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n /**\n * Check if the error is due to an expired token\n */\n isTokenExpired(): boolean {\n return this.authErrorType === 'token_expired';\n }\n\n /**\n * Check if the error is a 403 Forbidden\n */\n isForbidden(): boolean {\n return this.authErrorType === 'forbidden';\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n authErrorType: this.authErrorType,\n serverCode: this.serverCode,\n };\n }\n}\n\n/**\n * Error thrown when a request times out\n */\nexport class MPFTimeoutError extends MPFError {\n /** The timeout duration in milliseconds */\n readonly timeoutMs: number;\n\n constructor(message: string, timeoutMs: number) {\n super(message, 'TIMEOUT_ERROR');\n this.name = 'MPFTimeoutError';\n this.timeoutMs = timeoutMs;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n timeoutMs: this.timeoutMs,\n };\n }\n}\n\n/**\n * Type guard to check if an error is an MPFError\n */\nexport function isMPFError(error: unknown): error is MPFError {\n return error instanceof MPFError;\n}\n\n/**\n * Type guard to check if an error is an MPFAuthError\n */\nexport function isMPFAuthError(error: unknown): error is MPFAuthError {\n return error instanceof MPFAuthError;\n}\n\n/**\n * Type guard to check if an error is an MPFAPIError\n */\nexport function isMPFAPIError(error: unknown): error is MPFAPIError {\n return error instanceof MPFAPIError;\n}\n\n/**\n * Type guard to check if an error is an MPFNetworkError\n */\nexport function isMPFNetworkError(error: unknown): error is MPFNetworkError {\n return error instanceof MPFNetworkError;\n}\n\n/**\n * Type guard to check if an error is an MPFValidationError\n */\nexport function isMPFValidationError(error: unknown): error is MPFValidationError {\n return error instanceof MPFValidationError;\n}\n","/**\n * Errors for the auth layer.\n */\n\nimport { MPFError } from '../client/core/errors.js';\n\n/**\n * Base error for access-token claim decoding failures.\n */\nexport class MPFClaimsError extends MPFError {\n constructor(message: string, code = 'CLAIMS_INVALID', details?: unknown) {\n super(message, code, undefined, details);\n this.name = 'MPFClaimsError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Thrown when a token's claim-set version has no registered parser.\n *\n * Carries the offending version so a client can distinguish \"this app is older\n * than the server\" (a deploy-ordering problem, usually fixed by reloading) from\n * \"this token is garbage\" (a real auth failure).\n */\nexport class MPFUnsupportedClaimsVersionError extends MPFClaimsError {\n /** The `v` value found in the token, or null when it was absent/non-numeric. */\n readonly version: number | null;\n\n constructor(version: number | null) {\n super(\n version === null\n ? 'Access token has no claims version (`v`)'\n : `Unsupported access token claims version: ${version}`,\n 'CLAIMS_UNSUPPORTED_VERSION',\n { version },\n );\n this.name = 'MPFUnsupportedClaimsVersionError';\n this.version = version;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return { ...super.toJSON(), version: this.version };\n }\n}\n\n/**\n * Thrown when the session can no longer be renewed and the user must\n * re-authenticate.\n *\n * This is a terminal state: the refresh token was rejected, absent, or the\n * renew endpoint failed in a non-recoverable way.\n */\nexport class DeadSessionError extends MPFError {\n /** The underlying error that killed the session, when there was one. */\n readonly cause?: Error;\n\n constructor(message = 'Session is no longer valid', cause?: Error) {\n super(message, 'DEAD_SESSION', 401);\n this.name = 'DeadSessionError';\n this.cause = cause;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return { ...super.toJSON(), cause: this.cause?.message };\n }\n}\n\n/**\n * Type guard for {@link DeadSessionError}.\n */\nexport function isDeadSession(error: unknown): error is DeadSessionError {\n return error instanceof DeadSessionError;\n}\n","/**\n * ============================================================================\n * SECURITY BOUNDARY — READ BEFORE USING ANYTHING IN THIS FILE\n * ============================================================================\n *\n * This module DECODES access tokens. It does NOT VERIFY them.\n *\n * There is no signature check here. There is no key material here. We call\n * `jose.decodeJwt`, which base64-decodes the payload and nothing else — an\n * unsigned token, a token signed with the wrong key, and a token whose payload\n * was hand-edited in devtools all decode identically and successfully.\n *\n * A hostile client can therefore forge ANY value this module returns: any user\n * id, any session id, any tenant, any role, any expiry.\n *\n * Every consumer of this module must be UX-only:\n * - rendering a tenant switcher,\n * - failing an obviously-invalid selection locally instead of round-tripping\n * for a 403,\n * - deciding when to proactively renew.\n *\n * NEVER gate a security-relevant branch on these values. The server is the only\n * authority: `hasura-authd` and `internal/go-chi-middleware-auth` verify the\n * signature and re-derive tenant and role from the token on every single\n * request, and a forged claim buys the attacker exactly nothing there.\n *\n * `jwtVerify` must never appear in this package. Verification needs the signing\n * secret, and the signing secret must never reach a browser.\n * ============================================================================\n */\n\nimport { decodeJwt } from 'jose';\n\nimport type {\n ClaimsParser,\n MPFClaims,\n MPFClaimsV1,\n MPFRole,\n MPFTenantClaim,\n} from './claims-types.js';\nimport { MPFClaimsError, MPFUnsupportedClaimsVersionError } from './errors.js';\n\n/** Maximum number of decoded token payloads kept in memory. */\nconst CLAIMS_CACHE_MAX = 5;\n\n/**\n * LRU cache of successful decodes, keyed on the raw token string.\n *\n * Keyed on the token itself, never on `uid`/`sid` — keying on an identity claim\n * would let a tampered token collide with a legitimate entry.\n *\n * Insertion-ordered `Map`: a hit is re-inserted to move it to the back, so\n * eviction takes the least-recently-*used* entry rather than the oldest.\n * Failures are never cached.\n */\nconst claimsCache = new Map<string, MPFClaims>();\n\nfunction cacheGet(token: string): MPFClaims | undefined {\n const hit = claimsCache.get(token);\n if (hit === undefined) {\n return undefined;\n }\n // Bump to most-recently-used.\n claimsCache.delete(token);\n claimsCache.set(token, hit);\n return hit;\n}\n\nfunction cachePut(token: string, claims: MPFClaims): void {\n if (claimsCache.has(token)) {\n claimsCache.delete(token);\n }\n claimsCache.set(token, claims);\n\n while (claimsCache.size > CLAIMS_CACHE_MAX) {\n const oldest = claimsCache.keys().next();\n if (oldest.done) {\n break;\n }\n claimsCache.delete(oldest.value);\n }\n}\n\n/**\n * Drop every cached decode.\n *\n * Call on logout so a decoded token cannot outlive the session in memory.\n */\nexport function clearClaimsCache(): void {\n claimsCache.clear();\n}\n\n// ---------------------------------------------------------------------------\n// Field helpers\n// ---------------------------------------------------------------------------\n\nfunction requireString(payload: Record<string, unknown>, key: string): string {\n const value = payload[key];\n if (typeof value !== 'string' || value.length === 0) {\n throw new MPFClaimsError(`Claim \"${key}\" must be a non-empty string`);\n }\n return value;\n}\n\nfunction requireNumber(payload: Record<string, unknown>, key: string): number {\n const value = payload[key];\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new MPFClaimsError(`Claim \"${key}\" must be a finite number`);\n }\n return value;\n}\n\nfunction optionalNumber(payload: Record<string, unknown>, key: string): number | undefined {\n const value = payload[key];\n if (value === undefined) {\n return undefined;\n }\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new MPFClaimsError(`Claim \"${key}\" must be a finite number when present`);\n }\n return value;\n}\n\n/**\n * A claim whose EMPTY state is meaningful, so absence degrades instead of\n * throwing.\n *\n * `drl` is emitted without `omitempty` on the Go side, so it arrives as `\"\"`\n * rather than vanishing when a deployment has no tenantless role configured.\n * Nothing the client does with it is load-bearing — the server decides the\n * effective role regardless — so an empty value becomes `undefined` rather than\n * locking the user out of decoding their own token. A wrong *type* still throws:\n * that is corruption, not absence.\n */\nfunction optionalString(payload: Record<string, unknown>, key: string): string | undefined {\n const value = payload[key];\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n if (typeof value !== 'string') {\n throw new MPFClaimsError(`Claim \"${key}\" must be a string when present`);\n }\n return value;\n}\n\n/**\n * Read the tenant array, treating absence as \"no tenants\".\n *\n * `tnts` is a mandatory claim carrying no `omitempty`, and `Mint` normalises a\n * nil slice to `[]`, so the server always emits an array. Tolerating absence\n * here anyway is defence in depth on a cross-repo contract: the SDK is the half\n * that ships to consumers who cannot patch the server, and \"no tenants\" is a\n * legitimate state rather than a malformed token — an earlier `omitempty` on the\n * Go field made every fresh signup undecodable.\n *\n * A `tnts` of the wrong TYPE still throws — coercing an object or a string to an\n * empty array would hide a real server bug behind an empty switcher.\n */\nfunction requireTenantList(payload: Record<string, unknown>): MPFTenantClaim[] {\n const value = payload['tnts'];\n\n // Absent or explicitly null: a user with no tenants.\n if (value === undefined || value === null) {\n return [];\n }\n\n if (!Array.isArray(value)) {\n throw new MPFClaimsError('Claim \"tnts\" must be an array when present');\n }\n\n return value.map((entry, i) => {\n if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) {\n throw new MPFClaimsError(`Claim \"tnts[${i}]\" must be an object`);\n }\n const record = entry as Record<string, unknown>;\n\n const id = record['id'];\n if (typeof id !== 'string' || id.length === 0) {\n throw new MPFClaimsError(`Claim \"tnts[${i}].id\" must be a non-empty string`);\n }\n\n const rls = record['rls'];\n if (!Array.isArray(rls) || rls.some((role) => typeof role !== 'string')) {\n throw new MPFClaimsError(`Claim \"tnts[${i}].rls\" must be an array of strings`);\n }\n\n const tenant: MPFTenantClaim = { id, rls: [...(rls as MPFRole[])] };\n\n // dfr is OPTIONAL. Absent means \"no explicit default\" — see\n // defaultRoleForTenant, which falls back to rls[0]. A present-but-wrong\n // TYPE still throws: that is corruption, not absence.\n const dfr = record['dfr'];\n if (dfr !== undefined && dfr !== null && dfr !== '') {\n if (typeof dfr !== 'string') {\n throw new MPFClaimsError(`Claim \"tnts[${i}].dfr\" must be a string when present`);\n }\n tenant.dfr = dfr;\n }\n\n return tenant;\n });\n}\n\n/** The `tnts` entry for a tenant id, or `undefined`. */\nfunction findTenant(claims: MPFClaims, tenantId: string): MPFTenantClaim | undefined {\n return claims.tnts.find((t) => t.id === tenantId);\n}\n\n// ---------------------------------------------------------------------------\n// Parser registry\n// ---------------------------------------------------------------------------\n\n/**\n * v1 parser.\n *\n * Reads only the keys it knows about, so a field added on the Go side cannot\n * brick an older client. Unknown *versions* are rejected; unknown *keys* are\n * ignored.\n */\nconst parseV1: ClaimsParser = (payload) => {\n // Hard-required vs degrading is a deliberate line:\n //\n // REQUIRED — absence means the token cannot be interpreted at all.\n // v : without a version we do not know how to read the rest.\n // exp : a token with no expiry must not be trusted.\n // uid : a session attributed to nobody would render a UI for nobody.\n // sid : likewise; Go emits both without `omitempty` and neither is ever\n // legitimately empty.\n //\n // DEGRADING — the empty state is a real, expected state.\n // tnts : a brand-new user belongs to no tenants (an empty array).\n // drl : a deployment may have no tenantless role configured.\n // iat : only needed for the renewal-buffer clamp, which falls back.\n //\n // The through-line: a server-side regression in a non-essential claim must\n // not lock a user out of decoding their own token, but a claim we cannot\n // proceed without should fail loudly rather than silently default.\n const claims: MPFClaimsV1 = {\n v: 1,\n uid: requireString(payload, 'uid'),\n sid: requireString(payload, 'sid'),\n exp: requireNumber(payload, 'exp'),\n tnts: requireTenantList(payload),\n };\n\n const drl = optionalString(payload, 'drl');\n if (drl !== undefined) {\n claims.drl = drl;\n }\n\n const iat = optionalNumber(payload, 'iat');\n if (iat !== undefined) {\n claims.iat = iat;\n }\n\n return claims;\n};\n\n/**\n * Version → parser. Explicit registry rather than an if-chain, so a future v2\n * is one added entry and the two versions coexist during a rollout.\n */\nconst PARSERS = new Map<number, ClaimsParser>([[1, parseV1]]);\n\n/**\n * Register a parser for a claim-set version.\n *\n * Exported so a consumer pinned to an older SDK can teach it a newer shape\n * without waiting for a release.\n *\n * @throws {MPFClaimsError} If the version already has a parser — a silent\n * overwrite would make decoding depend on module import order.\n */\nexport function registerClaimsParser(version: number, parser: ClaimsParser): void {\n if (PARSERS.has(version)) {\n throw new MPFClaimsError(`A parser is already registered for claims version ${version}`);\n }\n PARSERS.set(version, parser);\n}\n\n/**\n * The claim-set versions this build understands.\n */\nexport function supportedClaimsVersions(): number[] {\n return [...PARSERS.keys()].sort((a, b) => a - b);\n}\n\n// ---------------------------------------------------------------------------\n// Decoding\n// ---------------------------------------------------------------------------\n\n/**\n * Decode an access token's claims.\n *\n * **Decodes, does not verify** — see the security block at the top of this file.\n *\n * Succeeds on an EXPIRED token by design: the session manager needs `exp` in\n * order to decide that a renewal is due, so expiry is the caller's question,\n * not this function's. Use {@link isExpired} to ask it.\n *\n * @param token - Raw JWT string.\n * @returns The typed claims.\n * @throws {MPFUnsupportedClaimsVersionError} If `v` is absent or unknown.\n * @throws {MPFClaimsError} If the token is malformed or a claim has the wrong type.\n */\nexport function decodeAccessToken(token: string): MPFClaims {\n if (typeof token !== 'string' || token.length === 0) {\n throw new MPFClaimsError('Access token must be a non-empty string');\n }\n\n const cached = cacheGet(token);\n if (cached !== undefined) {\n return cached;\n }\n\n let payload: Record<string, unknown>;\n try {\n payload = decodeJwt(token) as Record<string, unknown>;\n } catch (error) {\n throw new MPFClaimsError(\n `Access token is not a decodable JWT: ${error instanceof Error ? error.message : 'unknown error'}`,\n 'CLAIMS_MALFORMED',\n );\n }\n\n const rawVersion = payload['v'];\n if (typeof rawVersion !== 'number' || !Number.isFinite(rawVersion)) {\n throw new MPFUnsupportedClaimsVersionError(null);\n }\n\n const parser = PARSERS.get(rawVersion);\n if (!parser) {\n throw new MPFUnsupportedClaimsVersionError(rawVersion);\n }\n\n const claims = parser(payload);\n cachePut(token, claims);\n return claims;\n}\n\n/**\n * Decode an access token, returning `null` instead of throwing.\n *\n * For UI paths that must render something regardless of token health.\n *\n * **Decodes, does not verify** — see the security block at the top of this file.\n */\nexport function tryDecodeAccessToken(token: string | null | undefined): MPFClaims | null {\n if (token === null || token === undefined || token === '') {\n return null;\n }\n try {\n return decodeAccessToken(token);\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Accessors\n// ---------------------------------------------------------------------------\n\n/**\n * Tenant ids present in the token, in `tnts` order.\n */\nexport function listTenants(claims: MPFClaims): string[] {\n return claims.tnts.map((tenant) => tenant.id);\n}\n\n/**\n * Roles held in a tenant.\n *\n * Returns a fresh array; mutating it cannot corrupt the cached claims.\n */\nexport function rolesForTenant(claims: MPFClaims, tenantId: string): MPFRole[] {\n const tenant = findTenant(claims, tenantId);\n return tenant ? [...tenant.rls] : [];\n}\n\n/**\n * The default role for a tenant: its explicit `dfr` when the entry carries one,\n * otherwise `rls[0]`.\n *\n * `undefined` when the tenant is not in the token, or holds no roles.\n */\nexport function defaultRoleForTenant(claims: MPFClaims, tenantId: string): MPFRole | undefined {\n const tenant = findTenant(claims, tenantId);\n if (tenant === undefined) {\n return undefined;\n }\n return tenant.dfr ?? tenant.rls[0];\n}\n\n/**\n * Whether a tenant (and optionally a role) *appears* selectable in this token.\n *\n * ⚠️ **NOT A PERMISSION CHECK.** This reads unverified, client-forgeable claims.\n * It exists so a switcher can grey out an entry and so an obviously-invalid\n * selection fails locally instead of costing a round trip for a 403. A `true`\n * here grants nothing: the server re-derives tenant and role from the verified\n * token on every request and will reject a selection this function approved.\n * Never branch on it for anything that must hold.\n *\n * @param claims - Decoded (unverified) claims.\n * @param tenantId - Tenant to select, or `null` for the no-tenant path.\n * @param role - Optional specific role; omitted means \"the tenant's default\".\n */\nexport function canSelect(\n claims: MPFClaims,\n tenantId: string | null,\n role?: MPFRole,\n): boolean {\n // The no-tenant path resolves to `drl` server-side.\n if (tenantId === null) {\n return role === undefined || role === claims.drl;\n }\n\n const tenant = findTenant(claims, tenantId);\n if (!tenant || tenant.rls.length === 0) {\n return false;\n }\n\n // `dfr` narrows which role is DEFAULTED to, never which roles may be named,\n // so the membership check stays against `rls`.\n return role === undefined || tenant.rls.includes(role);\n}\n\n/**\n * The token's expiry as a `Date`.\n */\nexport function expiresAt(claims: MPFClaims): Date {\n return new Date(claims.exp * 1000);\n}\n\n/**\n * Whether the token is expired, optionally treating it as expired\n * `skewSeconds` early.\n *\n * @param claims - Decoded claims.\n * @param skewSeconds - Seconds of headroom. `120` answers \"will this token die\n * within the next two minutes?\", which is the question a renewal buffer asks.\n * @param nowMs - Injectable clock for tests. Defaults to `Date.now()`.\n */\nexport function isExpired(claims: MPFClaims, skewSeconds = 0, nowMs?: number): boolean {\n const now = (nowMs ?? Date.now()) / 1000;\n return claims.exp - skewSeconds <= now;\n}\n\n/**\n * Token lifetime in seconds (`exp - iat`), or `undefined` when the token\n * carries no `iat`.\n */\nexport function tokenLifetimeSeconds(claims: MPFClaims): number | undefined {\n if (claims.iat === undefined) {\n return undefined;\n }\n const lifetime = claims.exp - claims.iat;\n return lifetime > 0 ? lifetime : undefined;\n}\n"]}
1
+ {"version":3,"sources":["../src/client/core/errors.ts","../src/auth/errors.ts","../src/auth/claims.ts"],"names":[],"mappings":"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","file":"chunk-S5DKGPUY.js","sourcesContent":["/**\n * Custom error classes for the MPF SDK\n */\n\n/**\n * Base error class for all MPF SDK errors\n */\nexport class MPFError extends Error {\n /** Machine-readable error code */\n readonly code: string;\n /** HTTP status code if applicable */\n readonly status?: number;\n /** Additional error details from the API */\n readonly details?: unknown;\n\n constructor(message: string, code: string, status?: number, details?: unknown) {\n super(message);\n this.name = 'MPFError';\n this.code = code;\n this.status = status;\n this.details = details;\n\n // Maintains proper stack trace for where error was thrown (V8 engines)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n\n // Ensure prototype chain is properly set for instanceof checks\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n /**\n * Convert error to a plain object for logging/serialization\n */\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n details: this.details,\n };\n }\n}\n\n/**\n * Error thrown when a network request fails (e.g., no connection, DNS failure)\n */\nexport class MPFNetworkError extends MPFError {\n /** The original error that caused the network failure */\n readonly cause?: Error;\n\n constructor(message: string, cause?: Error) {\n super(message, 'NETWORK_ERROR');\n this.name = 'MPFNetworkError';\n this.cause = cause;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n cause: this.cause?.message,\n };\n }\n}\n\n/**\n * Error thrown when the API returns an error response\n */\nexport class MPFAPIError extends MPFError {\n /** The raw response body if available */\n readonly body?: unknown;\n\n constructor(message: string, code: string, status: number, details?: unknown, body?: unknown) {\n super(message, code, status, details);\n this.name = 'MPFAPIError';\n this.body = body;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n body: this.body,\n };\n }\n}\n\n/**\n * Error thrown when request validation fails (e.g., invalid parameters)\n */\nexport class MPFValidationError extends MPFError {\n /** Field-specific validation errors */\n readonly fieldErrors?: Record<string, string[]>;\n\n constructor(message: string, details?: unknown, fieldErrors?: Record<string, string[]>) {\n super(message, 'VALIDATION_ERROR', 400, details);\n this.name = 'MPFValidationError';\n this.fieldErrors = fieldErrors;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n fieldErrors: this.fieldErrors,\n };\n }\n}\n\n/**\n * Error thrown when authentication or authorization fails (401/403)\n */\nexport class MPFAuthError extends MPFError {\n /** The type of auth error (e.g., 'unauthorized', 'forbidden', 'token_expired') */\n readonly authErrorType: 'unauthorized' | 'forbidden' | 'token_expired' | 'invalid_token';\n\n /**\n * The machine-readable code the server actually sent, when it sent one.\n *\n * `code` is derived from {@link authErrorType} and therefore collapses every\n * 401 to `UNAUTHORIZED`, which loses information the server deliberately\n * provides — `REFRESH_TOKEN_SUPERSEDED` being the case that matters: it means\n * \"another tab renewed first\", which is recoverable by adopting that tab's\n * token, and must not be treated as a dead session.\n *\n * Kept as a separate field rather than overwriting `code` so that existing\n * consumers switching on `code` are unaffected.\n */\n readonly serverCode?: string;\n\n constructor(\n message: string,\n authErrorType: 'unauthorized' | 'forbidden' | 'token_expired' | 'invalid_token',\n status: 401 | 403 = 401,\n details?: unknown,\n serverCode?: string\n ) {\n const code = authErrorType.toUpperCase();\n super(message, code, status, details);\n this.name = 'MPFAuthError';\n this.authErrorType = authErrorType;\n this.serverCode = serverCode;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n /**\n * Check if the error is due to an expired token\n */\n isTokenExpired(): boolean {\n return this.authErrorType === 'token_expired';\n }\n\n /**\n * Check if the error is a 403 Forbidden\n */\n isForbidden(): boolean {\n return this.authErrorType === 'forbidden';\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n authErrorType: this.authErrorType,\n serverCode: this.serverCode,\n };\n }\n}\n\n/**\n * Error thrown when a request times out\n */\nexport class MPFTimeoutError extends MPFError {\n /** The timeout duration in milliseconds */\n readonly timeoutMs: number;\n\n constructor(message: string, timeoutMs: number) {\n super(message, 'TIMEOUT_ERROR');\n this.name = 'MPFTimeoutError';\n this.timeoutMs = timeoutMs;\n\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return {\n ...super.toJSON(),\n timeoutMs: this.timeoutMs,\n };\n }\n}\n\n/**\n * Type guard to check if an error is an MPFError\n */\nexport function isMPFError(error: unknown): error is MPFError {\n return error instanceof MPFError;\n}\n\n/**\n * Type guard to check if an error is an MPFAuthError\n */\nexport function isMPFAuthError(error: unknown): error is MPFAuthError {\n return error instanceof MPFAuthError;\n}\n\n/**\n * Type guard to check if an error is an MPFAPIError\n */\nexport function isMPFAPIError(error: unknown): error is MPFAPIError {\n return error instanceof MPFAPIError;\n}\n\n/**\n * Type guard to check if an error is an MPFNetworkError\n */\nexport function isMPFNetworkError(error: unknown): error is MPFNetworkError {\n return error instanceof MPFNetworkError;\n}\n\n/**\n * Type guard to check if an error is an MPFValidationError\n */\nexport function isMPFValidationError(error: unknown): error is MPFValidationError {\n return error instanceof MPFValidationError;\n}\n","/**\n * Errors for the auth layer.\n */\n\nimport { MPFError } from '../client/core/errors.js';\n\n/**\n * Base error for access-token claim decoding failures.\n */\nexport class MPFClaimsError extends MPFError {\n constructor(message: string, code = 'CLAIMS_INVALID', details?: unknown) {\n super(message, code, undefined, details);\n this.name = 'MPFClaimsError';\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n\n/**\n * Thrown when a token's claim-set version has no registered parser.\n *\n * Carries the offending version so a client can distinguish \"this app is older\n * than the server\" (a deploy-ordering problem, usually fixed by reloading) from\n * \"this token is garbage\" (a real auth failure).\n */\nexport class MPFUnsupportedClaimsVersionError extends MPFClaimsError {\n /** The `v` value found in the token, or null when it was absent/non-numeric. */\n readonly version: number | null;\n\n constructor(version: number | null) {\n super(\n version === null\n ? 'Access token has no claims version (`v`)'\n : `Unsupported access token claims version: ${version}`,\n 'CLAIMS_UNSUPPORTED_VERSION',\n { version },\n );\n this.name = 'MPFUnsupportedClaimsVersionError';\n this.version = version;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return { ...super.toJSON(), version: this.version };\n }\n}\n\n/**\n * Thrown when the session can no longer be renewed and the user must\n * re-authenticate.\n *\n * This is a terminal state: the refresh token was rejected, absent, or the\n * renew endpoint failed in a non-recoverable way.\n */\nexport class DeadSessionError extends MPFError {\n /** The underlying error that killed the session, when there was one. */\n readonly cause?: Error;\n\n constructor(message = 'Session is no longer valid', cause?: Error) {\n super(message, 'DEAD_SESSION', 401);\n this.name = 'DeadSessionError';\n this.cause = cause;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n override toJSON(): Record<string, unknown> {\n return { ...super.toJSON(), cause: this.cause?.message };\n }\n}\n\n/**\n * Type guard for {@link DeadSessionError}.\n */\nexport function isDeadSession(error: unknown): error is DeadSessionError {\n return error instanceof DeadSessionError;\n}\n","/**\n * ============================================================================\n * SECURITY BOUNDARY — READ BEFORE USING ANYTHING IN THIS FILE\n * ============================================================================\n *\n * This module DECODES access tokens. It does NOT VERIFY them.\n *\n * There is no signature check here. There is no key material here. We call\n * `jose.decodeJwt`, which base64-decodes the payload and nothing else — an\n * unsigned token, a token signed with the wrong key, and a token whose payload\n * was hand-edited in devtools all decode identically and successfully.\n *\n * A hostile client can therefore forge ANY value this module returns: any user\n * id, any session id, any tenant, any role, any expiry.\n *\n * Every consumer of this module must be UX-only:\n * - rendering a tenant switcher,\n * - failing an obviously-invalid selection locally instead of round-tripping\n * for a 403,\n * - deciding when to proactively renew.\n *\n * NEVER gate a security-relevant branch on these values. The server is the only\n * authority: `hasura-authd` and `pkg/go-chi-middleware-auth` verify the\n * signature and re-derive tenant and role from the token on every single\n * request, and a forged claim buys the attacker exactly nothing there.\n *\n * `jwtVerify` must never appear in this package. Verification needs the signing\n * secret, and the signing secret must never reach a browser.\n * ============================================================================\n */\n\nimport { decodeJwt } from 'jose';\n\nimport type {\n ClaimsParser,\n MPFClaims,\n MPFClaimsV1,\n MPFRole,\n MPFTenantClaim,\n} from './claims-types.js';\nimport { MPFClaimsError, MPFUnsupportedClaimsVersionError } from './errors.js';\n\n/** Maximum number of decoded token payloads kept in memory. */\nconst CLAIMS_CACHE_MAX = 5;\n\n/**\n * LRU cache of successful decodes, keyed on the raw token string.\n *\n * Keyed on the token itself, never on `uid`/`sid` — keying on an identity claim\n * would let a tampered token collide with a legitimate entry.\n *\n * Insertion-ordered `Map`: a hit is re-inserted to move it to the back, so\n * eviction takes the least-recently-*used* entry rather than the oldest.\n * Failures are never cached.\n */\nconst claimsCache = new Map<string, MPFClaims>();\n\nfunction cacheGet(token: string): MPFClaims | undefined {\n const hit = claimsCache.get(token);\n if (hit === undefined) {\n return undefined;\n }\n // Bump to most-recently-used.\n claimsCache.delete(token);\n claimsCache.set(token, hit);\n return hit;\n}\n\nfunction cachePut(token: string, claims: MPFClaims): void {\n if (claimsCache.has(token)) {\n claimsCache.delete(token);\n }\n claimsCache.set(token, claims);\n\n while (claimsCache.size > CLAIMS_CACHE_MAX) {\n const oldest = claimsCache.keys().next();\n if (oldest.done) {\n break;\n }\n claimsCache.delete(oldest.value);\n }\n}\n\n/**\n * Drop every cached decode.\n *\n * Call on logout so a decoded token cannot outlive the session in memory.\n */\nexport function clearClaimsCache(): void {\n claimsCache.clear();\n}\n\n// ---------------------------------------------------------------------------\n// Field helpers\n// ---------------------------------------------------------------------------\n\nfunction requireString(payload: Record<string, unknown>, key: string): string {\n const value = payload[key];\n if (typeof value !== 'string' || value.length === 0) {\n throw new MPFClaimsError(`Claim \"${key}\" must be a non-empty string`);\n }\n return value;\n}\n\nfunction requireNumber(payload: Record<string, unknown>, key: string): number {\n const value = payload[key];\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new MPFClaimsError(`Claim \"${key}\" must be a finite number`);\n }\n return value;\n}\n\nfunction optionalNumber(payload: Record<string, unknown>, key: string): number | undefined {\n const value = payload[key];\n if (value === undefined) {\n return undefined;\n }\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n throw new MPFClaimsError(`Claim \"${key}\" must be a finite number when present`);\n }\n return value;\n}\n\n/**\n * A claim whose EMPTY state is meaningful, so absence degrades instead of\n * throwing.\n *\n * `drl` is emitted without `omitempty` on the Go side, so it arrives as `\"\"`\n * rather than vanishing when a deployment has no tenantless role configured.\n * Nothing the client does with it is load-bearing — the server decides the\n * effective role regardless — so an empty value becomes `undefined` rather than\n * locking the user out of decoding their own token. A wrong *type* still throws:\n * that is corruption, not absence.\n */\nfunction optionalString(payload: Record<string, unknown>, key: string): string | undefined {\n const value = payload[key];\n if (value === undefined || value === null || value === '') {\n return undefined;\n }\n if (typeof value !== 'string') {\n throw new MPFClaimsError(`Claim \"${key}\" must be a string when present`);\n }\n return value;\n}\n\n/**\n * Read the tenant array, treating absence as \"no tenants\".\n *\n * `tnts` is a mandatory claim carrying no `omitempty`, and `Mint` normalises a\n * nil slice to `[]`, so the server always emits an array. Tolerating absence\n * here anyway is defence in depth on a cross-repo contract: the SDK is the half\n * that ships to consumers who cannot patch the server, and \"no tenants\" is a\n * legitimate state rather than a malformed token — an earlier `omitempty` on the\n * Go field made every fresh signup undecodable.\n *\n * A `tnts` of the wrong TYPE still throws — coercing an object or a string to an\n * empty array would hide a real server bug behind an empty switcher.\n */\nfunction requireTenantList(payload: Record<string, unknown>): MPFTenantClaim[] {\n const value = payload['tnts'];\n\n // Absent or explicitly null: a user with no tenants.\n if (value === undefined || value === null) {\n return [];\n }\n\n if (!Array.isArray(value)) {\n throw new MPFClaimsError('Claim \"tnts\" must be an array when present');\n }\n\n return value.map((entry, i) => {\n if (typeof entry !== 'object' || entry === null || Array.isArray(entry)) {\n throw new MPFClaimsError(`Claim \"tnts[${i}]\" must be an object`);\n }\n const record = entry as Record<string, unknown>;\n\n const id = record['id'];\n if (typeof id !== 'string' || id.length === 0) {\n throw new MPFClaimsError(`Claim \"tnts[${i}].id\" must be a non-empty string`);\n }\n\n const rls = record['rls'];\n if (!Array.isArray(rls) || rls.some((role) => typeof role !== 'string')) {\n throw new MPFClaimsError(`Claim \"tnts[${i}].rls\" must be an array of strings`);\n }\n\n const tenant: MPFTenantClaim = { id, rls: [...(rls as MPFRole[])] };\n\n // dfr is OPTIONAL. Absent means \"no explicit default\" — see\n // defaultRoleForTenant, which falls back to rls[0]. A present-but-wrong\n // TYPE still throws: that is corruption, not absence.\n const dfr = record['dfr'];\n if (dfr !== undefined && dfr !== null && dfr !== '') {\n if (typeof dfr !== 'string') {\n throw new MPFClaimsError(`Claim \"tnts[${i}].dfr\" must be a string when present`);\n }\n tenant.dfr = dfr;\n }\n\n return tenant;\n });\n}\n\n/** The `tnts` entry for a tenant id, or `undefined`. */\nfunction findTenant(claims: MPFClaims, tenantId: string): MPFTenantClaim | undefined {\n return claims.tnts.find((t) => t.id === tenantId);\n}\n\n// ---------------------------------------------------------------------------\n// Parser registry\n// ---------------------------------------------------------------------------\n\n/**\n * v1 parser.\n *\n * Reads only the keys it knows about, so a field added on the Go side cannot\n * brick an older client. Unknown *versions* are rejected; unknown *keys* are\n * ignored.\n */\nconst parseV1: ClaimsParser = (payload) => {\n // Hard-required vs degrading is a deliberate line:\n //\n // REQUIRED — absence means the token cannot be interpreted at all.\n // v : without a version we do not know how to read the rest.\n // exp : a token with no expiry must not be trusted.\n // uid : a session attributed to nobody would render a UI for nobody.\n // sid : likewise; Go emits both without `omitempty` and neither is ever\n // legitimately empty.\n //\n // DEGRADING — the empty state is a real, expected state.\n // tnts : a brand-new user belongs to no tenants (an empty array).\n // drl : a deployment may have no tenantless role configured.\n // iat : only needed for the renewal-buffer clamp, which falls back.\n //\n // The through-line: a server-side regression in a non-essential claim must\n // not lock a user out of decoding their own token, but a claim we cannot\n // proceed without should fail loudly rather than silently default.\n const claims: MPFClaimsV1 = {\n v: 1,\n uid: requireString(payload, 'uid'),\n sid: requireString(payload, 'sid'),\n exp: requireNumber(payload, 'exp'),\n tnts: requireTenantList(payload),\n };\n\n const drl = optionalString(payload, 'drl');\n if (drl !== undefined) {\n claims.drl = drl;\n }\n\n const iat = optionalNumber(payload, 'iat');\n if (iat !== undefined) {\n claims.iat = iat;\n }\n\n return claims;\n};\n\n/**\n * Version → parser. Explicit registry rather than an if-chain, so a future v2\n * is one added entry and the two versions coexist during a rollout.\n */\nconst PARSERS = new Map<number, ClaimsParser>([[1, parseV1]]);\n\n/**\n * Register a parser for a claim-set version.\n *\n * Exported so a consumer pinned to an older SDK can teach it a newer shape\n * without waiting for a release.\n *\n * @throws {MPFClaimsError} If the version already has a parser — a silent\n * overwrite would make decoding depend on module import order.\n */\nexport function registerClaimsParser(version: number, parser: ClaimsParser): void {\n if (PARSERS.has(version)) {\n throw new MPFClaimsError(`A parser is already registered for claims version ${version}`);\n }\n PARSERS.set(version, parser);\n}\n\n/**\n * The claim-set versions this build understands.\n */\nexport function supportedClaimsVersions(): number[] {\n return [...PARSERS.keys()].sort((a, b) => a - b);\n}\n\n// ---------------------------------------------------------------------------\n// Decoding\n// ---------------------------------------------------------------------------\n\n/**\n * Decode an access token's claims.\n *\n * **Decodes, does not verify** — see the security block at the top of this file.\n *\n * Succeeds on an EXPIRED token by design: the session manager needs `exp` in\n * order to decide that a renewal is due, so expiry is the caller's question,\n * not this function's. Use {@link isExpired} to ask it.\n *\n * @param token - Raw JWT string.\n * @returns The typed claims.\n * @throws {MPFUnsupportedClaimsVersionError} If `v` is absent or unknown.\n * @throws {MPFClaimsError} If the token is malformed or a claim has the wrong type.\n */\nexport function decodeAccessToken(token: string): MPFClaims {\n if (typeof token !== 'string' || token.length === 0) {\n throw new MPFClaimsError('Access token must be a non-empty string');\n }\n\n const cached = cacheGet(token);\n if (cached !== undefined) {\n return cached;\n }\n\n let payload: Record<string, unknown>;\n try {\n payload = decodeJwt(token) as Record<string, unknown>;\n } catch (error) {\n throw new MPFClaimsError(\n `Access token is not a decodable JWT: ${error instanceof Error ? error.message : 'unknown error'}`,\n 'CLAIMS_MALFORMED',\n );\n }\n\n const rawVersion = payload['v'];\n if (typeof rawVersion !== 'number' || !Number.isFinite(rawVersion)) {\n throw new MPFUnsupportedClaimsVersionError(null);\n }\n\n const parser = PARSERS.get(rawVersion);\n if (!parser) {\n throw new MPFUnsupportedClaimsVersionError(rawVersion);\n }\n\n const claims = parser(payload);\n cachePut(token, claims);\n return claims;\n}\n\n/**\n * Decode an access token, returning `null` instead of throwing.\n *\n * For UI paths that must render something regardless of token health.\n *\n * **Decodes, does not verify** — see the security block at the top of this file.\n */\nexport function tryDecodeAccessToken(token: string | null | undefined): MPFClaims | null {\n if (token === null || token === undefined || token === '') {\n return null;\n }\n try {\n return decodeAccessToken(token);\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Accessors\n// ---------------------------------------------------------------------------\n\n/**\n * Tenant ids present in the token, in `tnts` order.\n */\nexport function listTenants(claims: MPFClaims): string[] {\n return claims.tnts.map((tenant) => tenant.id);\n}\n\n/**\n * Roles held in a tenant.\n *\n * Returns a fresh array; mutating it cannot corrupt the cached claims.\n */\nexport function rolesForTenant(claims: MPFClaims, tenantId: string): MPFRole[] {\n const tenant = findTenant(claims, tenantId);\n return tenant ? [...tenant.rls] : [];\n}\n\n/**\n * The default role for a tenant: its explicit `dfr` when the entry carries one,\n * otherwise `rls[0]`.\n *\n * `undefined` when the tenant is not in the token, or holds no roles.\n */\nexport function defaultRoleForTenant(claims: MPFClaims, tenantId: string): MPFRole | undefined {\n const tenant = findTenant(claims, tenantId);\n if (tenant === undefined) {\n return undefined;\n }\n return tenant.dfr ?? tenant.rls[0];\n}\n\n/**\n * Whether a tenant (and optionally a role) *appears* selectable in this token.\n *\n * ⚠️ **NOT A PERMISSION CHECK.** This reads unverified, client-forgeable claims.\n * It exists so a switcher can grey out an entry and so an obviously-invalid\n * selection fails locally instead of costing a round trip for a 403. A `true`\n * here grants nothing: the server re-derives tenant and role from the verified\n * token on every request and will reject a selection this function approved.\n * Never branch on it for anything that must hold.\n *\n * @param claims - Decoded (unverified) claims.\n * @param tenantId - Tenant to select, or `null` for the no-tenant path.\n * @param role - Optional specific role; omitted means \"the tenant's default\".\n */\nexport function canSelect(\n claims: MPFClaims,\n tenantId: string | null,\n role?: MPFRole,\n): boolean {\n // The no-tenant path resolves to `drl` server-side.\n if (tenantId === null) {\n return role === undefined || role === claims.drl;\n }\n\n const tenant = findTenant(claims, tenantId);\n if (!tenant || tenant.rls.length === 0) {\n return false;\n }\n\n // `dfr` narrows which role is DEFAULTED to, never which roles may be named,\n // so the membership check stays against `rls`.\n return role === undefined || tenant.rls.includes(role);\n}\n\n/**\n * The token's expiry as a `Date`.\n */\nexport function expiresAt(claims: MPFClaims): Date {\n return new Date(claims.exp * 1000);\n}\n\n/**\n * Whether the token is expired, optionally treating it as expired\n * `skewSeconds` early.\n *\n * @param claims - Decoded claims.\n * @param skewSeconds - Seconds of headroom. `120` answers \"will this token die\n * within the next two minutes?\", which is the question a renewal buffer asks.\n * @param nowMs - Injectable clock for tests. Defaults to `Date.now()`.\n */\nexport function isExpired(claims: MPFClaims, skewSeconds = 0, nowMs?: number): boolean {\n const now = (nowMs ?? Date.now()) / 1000;\n return claims.exp - skewSeconds <= now;\n}\n\n/**\n * Token lifetime in seconds (`exp - iat`), or `undefined` when the token\n * carries no `iat`.\n */\nexport function tokenLifetimeSeconds(claims: MPFClaims): number | undefined {\n if (claims.iat === undefined) {\n return undefined;\n }\n const lifetime = claims.exp - claims.iat;\n return lifetime > 0 ? lifetime : undefined;\n}\n"]}