import { Base } from './Base';
import FaableAuthApi from './FaableAuthApi';
import { BroadcastSync } from './lib/broadcast_sync';
import { AuthError } from './lib/errors';
import { Deferred } from './lib/helpers';
import { LastUsedLoginMethod } from './lib/last_used_storage';
import { getSessionFromCookies } from './lib/nextjs';
import { type PendingPasswordless } from './lib/pending_passwordless';
import { cookieStorageAdapter } from './lib/storage/cookie-storage';
import { AuthFlowType, AuthResult, CallRefreshTokenResult, GetTokenSilently, InitializeResult, JwtClaims, LastUsedCookieOptions, OAuthResponse, SignInWithOAuthConnection, SignupLoginOptions, SignupParams, SignupResult, Subscription, SupportedStorage, User } from './lib/types';
import { AuthChangeEvent, AuthResponse, FaableAuthClientConfig } from './lib/types';
import { ProfileUpdate, Session, SignOut, UserCredentials, UserSessions } from './lib/types';
import { Lock } from './lock/Lock';
export { cookieStorageAdapter, getSessionFromCookies };
/**
 * Error the auth server returned via redirect (`?error=...&
 * error_description=...`, RFC 6749 §4.1.2.1) on the page we initialized on,
 * with what this browser remembers of the round trip that failed.
 *
 * @see {@link FaableAuthClient.getRedirectError}
 */
export type RedirectError = {
    error: string;
    error_description: string;
    /** Stable machine code the server attached (`identity_already_linked`…). */
    error_code?: string;
    /**
     * The connection the failed round trip was started with, as passed to
     * `signInWithOauthConnection` / `linkOauthConnection`. Absent when the
     * failure was not a round trip this browser started (or its record
     * expired).
     */
    connection?: string;
    connection_id?: string;
    /** The round trip was a `linkOauthConnection`, not a sign-in. */
    link?: boolean;
    /** The `appState` the round trip was started with. */
    appState?: unknown;
    /** The `returnTo` the round trip was started with. */
    returnTo?: string;
};
/** Consume-once record of why the SDK terminated the session on its own. */
export type SignOutReason = {
    /** Stable machine code when the server sent one (e.g. `user_suspended`). */
    code?: string;
    /** Human-readable message from the terminal error. */
    message: string;
    /** Epoch ms when the session was terminated. */
    at: number;
};
/**
 * The main entry point of the SDK: an isomorphic client bound to a Faable
 * Auth tenant that drives every authentication flow.
 *
 * Prefer creating it through the {@link createClient} factory in app code.
 * Once instantiated it begins loading its session in the background, so you
 * can subscribe to {@link FaableAuthClient.onAuthStateChange | auth-state
 * changes} and trigger sign-ins right away. The most common starting points
 * are the {@link FaableAuthClient.signInWithOauthConnection | sign-in}
 * methods and {@link FaableAuthClient.getSession | getSession}.
 *
 * @category Getting started
 * @see {@link https://faable.com/docs/auth/get-started | Get Started with Faable Auth}
 */
export declare class FaableAuthClient extends Base {
    domainUrl: string;
    tokenIssuer: string;
    redirectUri: string;
    scope?: string;
    audience?: string;
    sessionCheckExpiryDays: number;
    protected initializePromise: Promise<InitializeResult> | null;
    protected _lastInitializeResult: InitializeResult | null;
    protected detectSessionInUrl: boolean;
    /**
     * Last step a `?code=` callback reached, sent along with a
     * {@link FaableAuthClient._reportSdk} report so the server log says WHERE it
     * stopped. `null` when this page load is not a callback.
     */
    protected _callbackStage: string | null;
    /**
     * First characters of the callback's `?code=`, sent with every report so the
     * server can join it with the `Generated code=` and `/oauth/token` lines of
     * the same sign-in — the IP is no key: on 2026-09-30 it changed mid-login.
     */
    protected _callbackCodePrefix: string | null;
    protected storageKey: string;
    protected clientId: string;
    protected storage: SupportedStorage;
    protected api: FaableAuthApi;
    protected autoRefreshToken: boolean;
    protected autoRefreshTicker: ReturnType<typeof setInterval> | null;
    protected visibilityChangedCallback: (() => Promise<any>) | null;
    protected refreshingDeferred: Deferred<CallRefreshTokenResult> | null;
    /**
     * Cross-tab broadcaster + local subscriber registry for state changes.
     */
    protected broadcastSync: BroadcastSync;
    protected _session: Session | null;
    /**
     * Initiation flow to use when redirecting to /authorize. Always PKCE in a
     * browser — it is what a tenant enforcing OAuth 2.1 accepts, and every
     * other tenant accepts it too, so the app needs no setting to follow its
     * tenant. `config.flowType` only chooses outside a browser (implicit by
     * default). Distinct from the callback-side flow, detected from URL params.
     */
    protected flowType: AuthFlowType;
    /** Attribute overrides for the "last used login method" hint cookie. */
    protected lastUsedCookie?: LastUsedCookieOptions;
    protected lock: Lock;
    /**
     * El `appState` del login que se está consumiendo ahora mismo.
     *
     * Existe por una razón concreta: los callbacks de `onAuthStateChange` se
     * ESPERAN, y `handleRedirectCallback()` es el propio `initialize()` en
     * vuelo, así que un listener que haga `await auth.handleRedirectCallback()`
     * dentro de `SIGNED_IN` se queda colgado para siempre. Este getter se puede
     * leer ahí de forma síncrona.
     */
    protected _appState: unknown;
    /**
     * Creates a new authentication client bound to a Faable Auth tenant.
     *
     * The constructor kicks off {@link FaableAuthClient.initialize} in the
     * background; you do not need to await anything before calling other methods.
     * Prefer the {@link createClient} factory in app code — it has the same
     * effect with less ceremony.
     *
     * @param config Tenant settings. `domain` and `clientId` are required and
     *   throw synchronously when missing.
     * @example
     * ```ts
     * const auth = new FaableAuthClient({
     *   domain: '<faableauth_domain>',
     *   clientId: '<client_id>',
     *   redirectUri: window.location.origin
     * })
     * ```
     * @see {@link https://faable.com/docs/auth/get-started | Get Started with Faable Auth}
     * @see {@link https://faable.com/docs/auth/clients | Clients}
     * @category Getting started
     */
    constructor(config: FaableAuthClientConfig);
    /**
     * Cached session value last persisted by the client.
     *
     * This is a synchronous accessor that returns whatever the client has
     * already loaded into memory. It can lag behind storage (for example,
     * across tabs before the broadcast event arrives) and never triggers a
     * refresh. Prefer {@link FaableAuthClient.getSession} when you need an
     * authoritative value, especially on the server.
     *
     * @returns The cached {@link Session} or `null` if no user is signed in.
     * @see {@link https://faable.com/docs/auth/oidc/userinfo | UserInfo}
     * @category Sessions
     */
    get session(): Session | null;
    /**
     * Initializes the client session either from the URL or from storage.
     *
     * Automatically called once from the constructor and idempotent — extra
     * calls return the same in-flight promise. Call it explicitly when you
     * need to await an OAuth, magic link, or password-recovery redirect to
     * finish processing so you can surface any returned error.
     *
     * @returns A promise that resolves to `{ error }` — non-null when the URL
     *   carried a failure or storage was corrupt; never throws.
     * @example
     * ```ts
     * const { error } = await auth.initialize()
     * if (error) console.error('Auth redirect failed', error)
     * ```
     * @see {@link https://faable.com/docs/auth/oauth-flows/authorization-code | Authorization Code with PKCE}
     * @category Lifecycle
     */
    initialize(): Promise<InitializeResult>;
    /**
     * On a `?code=` callback, arms the stall report and marks the first stage.
     * Returns the timer so {@link FaableAuthClient.initialize} can disarm it, or
     * `null` when this page load is not a callback.
     *
     * Armed in `initialize()` and not in `_initialize()` on purpose: a callback
     * stuck waiting for the lock never reaches `_initialize()`, and that is one
     * of the places it can hang.
     */
    private _watchCallback;
    /**
     * Disarms the stall report. If it already fired, the callback DID finish in
     * the end — slowly — and that is reported too (`callback_recovered`, with
     * the total time): the slowness that resolves itself is exactly what left no
     * trace before, since the person eventually gets in and nobody complains.
     */
    private _endCallbackWatch;
    private _setCallbackStage;
    /**
     * Tells the auth server that a sign-in could not be completed in this
     * browser (`POST /sdk/report`). Fire-and-forget: it never throws, never
     * blocks the caller and its outcome is ignored — the one thing it must not
     * do is become a second way for the callback to fail.
     *
     * `keepalive` so it still leaves if the person gives up and navigates away,
     * which is exactly what someone looking at a stuck spinner does.
     */
    private _reportSdk;
    /**
     * The result of the most recent {@link FaableAuthClient.initialize} run, or
     * `null` while the first one is still in flight.
     *
     * The constructor starts `initialize()` in the background and discards the
     * promise; this accessor lets code that cannot await it (for example a
     * React provider effect) read whether the last OAuth/redirect attempt
     * errored, instead of being stuck with a session that silently stays
     * `null`.
     *
     * @category Lifecycle
     */
    get lastInitializeResult(): InitializeResult | null;
    /**
     * Lo que la app pidió llevarse al arrancar el login ({@link SignInWithOAuthConnection.appState}),
     * ya deserializado, o `undefined` si no pidió nada.
     *
     * Es la misma información que `appState` en el resultado de
     * {@link FaableAuthClient.handleRedirectCallback}, pero **legible de forma
     * síncrona**, que es lo que hace falta dentro de un
     * {@link FaableAuthClient.onAuthStateChange}:
     *
     * ```ts
     * auth.onAuthStateChange((ev) => {
     *   if (ev === 'SIGNED_IN') console.log(auth.appState)
     * })
     * ```
     *
     * ⚠️ **No llames a `handleRedirectCallback()` dentro de un listener**: los
     * callbacks se esperan y ese método es el `initialize()` que los está
     * emitiendo, así que la promesa no resuelve nunca.
     */
    get appState(): unknown;
    /**
     * Completes an OAuth / magic-link / password-recovery redirect on your
     * callback route and reports the outcome.
     *
     * The SDK already consumes the URL during the `initialize()` it kicks off
     * from the constructor; this is a thin, discoverable wrapper that awaits
     * that same in-flight run (idempotent) so you can:
     *
     * - redirect **only once** the token exchange has finished, and
     * - surface `error` instead of hanging on a "Signing you in…" screen when
     *   the exchange fails (e.g. an expired PKCE verifier).
     *
     * It also returns `returnTo` — the app-side destination you optionally
     * passed to `signInWith*({ returnTo })` — so you don't need a side channel
     * (like `sessionStorage`) to remember where to send the user.
     *
     * @example
     * ```ts
     * // app/callback/page.tsx
     * const { error, returnTo } = await auth.handleRedirectCallback()
     * if (error) showError(error.message)
     * else router.replace(returnTo ?? '/')
     * ```
     * @see {@link FaableAuthClient.initialize}
     * @category Lifecycle
     */
    handleRedirectCallback(): Promise<InitializeResult>;
    /**
     * IMPORTANT:
     * 1. Never throw in this method, as it is called from the constructor
     * 2. Never return a session from this method as it would be cached over
     *    the whole lifetime of the client
     */
    private _initialize;
    /**
     * Gets the session data from a URL string
     */
    private _getSessionFromURL;
    private _exchangeCodeForSession;
    /**
     * Registers callbacks on the browser / platform, which in-turn run
     * algorithms when the browser window/tab are in foreground. On non-browser
     * platforms it assumes always foreground.
     */
    private _handleVisibilityChange;
    /**
     * Callback registered with `window.addEventListener('visibilitychange')`.
     */
    private _onVisibilityChanged;
    /**
     * Recovers the session from LocalStorage and refreshes
     * Note: this method is async to accommodate for AsyncStorage e.g. in React native.
     */
    private _recoverAndRefresh;
    /**
     * Removes any registered visibilitychange callback.
     *
     * @see startAutoRefresh
     * @see stopAutoRefresh
     */
    private _removeVisibilityChangedCallback;
    /**
     * Starts an auto-refresh process in the background. The session is checked
     * every few seconds. Close to the time of expiration a process is started to
     * refresh the session. If refreshing fails it will be retried for as long as
     * necessary.
     *
     * If `autoRefreshToken` is enabled in the client config you don't need to
     * call this function, it will be called for you.
     *
     * On browsers the refresh process works only when the tab/window is in the
     * foreground to conserve resources as well as prevent race conditions and
     * flooding auth with requests. If you call this method any managed
     * visibility change callback will be removed and you must manage visibility
     * changes on your own.
     *
     * On non-browser platforms the refresh process works *continuously* in the
     * background, which may not be desirable. You should hook into your
     * platform's foreground indication mechanism and call these methods
     * appropriately to conserve resources.
     *
     * @example
     * ```ts
     * // React Native / Node: drive the refresh loop on focus events yourself
     * appState.addEventListener('change', state => {
     *   if (state === 'active') auth.startAutoRefresh()
     * })
     * ```
     * @see {@link https://faable.com/docs/auth/oauth-flows/refresh-token | Refresh Token}
     * @category Sessions
     */
    startAutoRefresh(): Promise<void>;
    /**
     * This is the private implementation of {@link #startAutoRefresh}. Use this
     * within the library.
     */
    private _startAutoRefresh;
    /**
     * This is the private implementation of {@link #stopAutoRefresh}. Use this
     * within the library.
     */
    private _stopAutoRefresh;
    /**
     * Runs the auto refresh token tick.
     */
    private _autoRefreshTokenTick;
    private _detectFlowType;
    private _scope;
    private _getUrlForConnection;
    /**
     * Starts an OAuth / social login by redirecting the browser to the tenant's
     * `/authorize` endpoint for the chosen connection.
     *
     * In browsers the SDK redirects the current window unless
     * `skipBrowserRedirect` is `true`. On that redirect success path the returned
     * promise **never resolves** — the pending navigation owns the page, so a
     * loading state you tie to the `await` stays on until unload instead of
     * flashing back. Pass `skipBrowserRedirect: true` to get `{ data: { url } }`
     * back and drive the navigation yourself. PKCE is used by default in
     * browsers, falling back to the implicit flow elsewhere. Prefer
     * `connection_id` when known — the backend resolves it without an extra
     * lookup; `connection` (by name) is kept for legacy tenants.
     *
     * @example
     * ```ts
     * // The tenant's hosted login, with every connection the app offers. With a
     * // live SSO session it signs the user in without showing anything.
     * await auth.signInWithOauthConnection()
     *
     * // Redirects the current window; the promise does not resolve on success.
     * await auth.signInWithOauthConnection({
     *   connection: 'google',
     *   redirectTo: 'https://app.example.com/callback'
     * })
     *
     * // Or take over the navigation yourself:
     * const { data } = await auth.signInWithOauthConnection({
     *   connection: 'google',
     *   skipBrowserRedirect: true
     * })
     * window.location.assign(data.url)
     * ```
     * @see {@link https://faable.com/docs/auth/connections | Connections}
     * @see {@link https://faable.com/docs/auth/oauth-flows/authorization-code | Authorization Code with PKCE}
     * @category Sign in
     */
    signInWithOauthConnection(credentials?: SignInWithOAuthConnection): Promise<OAuthResponse>;
    /**
     * Sends the user to the tenant's hosted login, with every connection the
     * application offers. With a live SSO session (the user signed in to
     * another app of the tenant) it comes back signed in without showing
     * anything. Same as {@link signInWithOauthConnection}, which also takes a
     * specific connection.
     *
     * @example
     * ```ts
     * await auth.signIn()
     * await auth.signIn({ returnTo: '/settings' })
     * ```
     * @see {@link https://faable.com/docs/auth/hosted-login | Hosted login}
     * @category Sign in
     */
    signIn(options?: SignInWithOAuthConnection): Promise<OAuthResponse>;
    /**
     * Links an additional OAuth identity (e.g. GitHub) to the CURRENTLY
     * signed-in user — the identity round-trip proves control of the provider
     * account and attaches it to the session user; it never signs in, never
     * creates a user, and never touches the user's email or profile.
     *
     * This is NOT {@link signInWithOauthConnection}: a sign-in with an unknown
     * provider identity creates a brand-new user, which is exactly the
     * duplicate-account hole "connect" buttons used to fall into. Requires an
     * active session (the server returns `error=login_required` otherwise) and
     * must not be combined with `prompt: 'login'` (it would destroy the
     * session being linked to).
     *
     * On failure the server redirects back with `?error=...` — read it with
     * {@link getRedirectError} after the round-trip.
     *
     * @example
     * ```ts
     * await auth.linkOauthConnection({
     *   connection_id: GITHUB_CONNECTION_ID,
     *   redirectTo: window.location.href
     * })
     * ```
     * @see {@link https://faable.com/docs/auth/connections | Connections}
     * @category Sign in
     */
    linkOauthConnection(credentials: SignInWithOAuthConnection): Promise<OAuthResponse>;
    /**
     * Trades the current access token for a single-use link ticket
     * (`POST /oauth/link_ticket`). Best-effort by design: no session, an
     * older server without the endpoint, an expired token or a network error
     * all resolve to `null`, and the link round-trip proceeds without a
     * ticket — the server then answers exactly as it did before tickets
     * existed (`login_required` unless it has a cookie session).
     */
    private _mintLinkTicket;
    /**
     * Signs the user in with a username + password against a database
     * connection on the tenant.
     *
     * The server responds with an HTML form that posts the user back to the
     * tenant's `/login/callback` to complete the OAuth flow; the SDK
     * auto-submits it from the current document. That is why the success path
     * resolves to `{ data: null, error: null }` — the actual session lands on
     * the redirect target, not on this return value. Subscribe with
     * {@link FaableAuthClient.onAuthStateChange} to observe the resulting
     * `SIGNED_IN` event.
     *
     * @example
     * ```ts
     * await auth.signInWithUsernamePassword({
     *   username: 'user@example.com',
     *   password: '••••••••',
     *   redirectTo: 'https://app.example.com/callback'
     * })
     * ```
     * @see {@link https://faable.com/docs/auth/connections | Connections}
     * @category Sign in
     */
    signInWithUsernamePassword(data: {
        username: string;
        password: string;
        redirectTo?: string;
        state?: string;
        audience?: string;
    }): Promise<AuthResult<null>>;
    /**
     * Creates a user in the tenant's database connection, and nothing else: no
     * login, no navigation. The browser-side counterpart of Auth0's
     * `webAuth.signup()` — a contact or waitlist form can register people
     * without a backend of its own.
     *
     * Calls the public `POST /dbconnections/signup`. Which identifier is required
     * follows the connection's login identifier (email, username or either), and
     * the password is optional: a user created without one sets it through the
     * password reset email. Unlike Auth0, which rejects a signup without password,
     * Faable neither generates one nor stores an empty one — the credential just
     * has no password yet.
     *
     * The user is created with `email_verified: false`; any verification /
     * welcome email is driven by the tenant's account settings.
     *
     * @param data The new user's identifier(s), optional password and profile fields.
     * @example
     * ```ts
     * const { data, error } = await auth.signup({
     *   email: 'user@example.com',
     *   name: 'Ada Lovelace',
     *   user_metadata: { source: 'contact-form' }
     * })
     * if (error?.code === 'email_exists') showAlreadyRegistered()
     * else if (error) showError(error.message)
     * else console.log('created', data.user_id)
     * ```
     * @see {@link https://faable.com/docs/auth/connections | Connections}
     * @category Sign in
     */
    signup(data: SignupParams): Promise<AuthResult<SignupResult>>;
    /**
     * Creates a user with {@link FaableAuthClient.signup} and then signs them
     * in — the counterpart of Auth0's `signupAndLogin`.
     *
     * **The login navigates the browser.** Like every interactive
     * username/password login in this SDK, it submits a form that round-trips
     * through the auth server, so on success the page redirects to your
     * `redirectTo` and the live session is delivered there by
     * {@link FaableAuthClient.initialize} (and a `SIGNED_IN` event). This method
     * only returns when the signup or the login fails, or in non-navigating
     * runtimes (e.g. tests). The password is required here: without one there is
     * nothing to sign in with.
     *
     * @param data The new user, with its password, plus where the login lands.
     * @example
     * ```ts
     * const { error } = await auth.signupAndLogin({
     *   email: 'user@example.com',
     *   password: '••••••••',
     *   redirectTo: 'https://app.example.com/callback'
     * })
     * if (error) showError(error.message) // e.g. email_exists, weak_password
     * // otherwise the browser is already navigating to complete the login
     * ```
     * @category Sign in
     */
    signupAndLogin(data: SignupParams & {
        password: string;
    } & SignupLoginOptions): Promise<AuthResult<null>>;
    /**
     * Registers a new user and, by default, signs them in.
     *
     * Kept for compatibility: with `signIn` unset or `true` it is
     * {@link FaableAuthClient.signupAndLogin} (the browser navigates on
     * success); with `signIn: false` it is {@link FaableAuthClient.signup} and
     * returns the created user. New code should call one of those two directly.
     *
     * @param data The new user, plus `signIn` and where the login lands.
     * @example
     * ```ts
     * const { error } = await auth.signUp({
     *   email: 'user@example.com',
     *   password: '••••••••',
     *   name: 'Ada Lovelace',
     *   redirectTo: 'https://app.example.com/callback'
     * })
     * if (error) showError(error.message) // e.g. 'email_exists', 'signup_disabled'
     * // otherwise the browser is already navigating to complete the login
     * ```
     * @see {@link https://faable.com/docs/auth/connections | Connections}
     * @category Sign in
     */
    signUp(data: SignupParams & SignupLoginOptions & {
        signIn: false;
    }): Promise<AuthResult<SignupResult>>;
    signUp(data: SignupParams & SignupLoginOptions & {
        signIn?: true;
    }): Promise<AuthResult<null>>;
    /**
     * Completes a passwordless login by exchanging an OTP code for a session.
     *
     * Pair this with {@link FaableAuthClient.signInWithPasswordless} called
     * with `type: 'code'`. On success the new session is persisted to storage
     * and a `SIGNED_IN` event is broadcast.
     *
     * @param data The user identifier and the OTP code they received.
     * @example
     * ```ts
     * const { data, error } = await auth.signInWithOtp({
     *   username: 'user@example.com',
     *   otp: '123456'
     * })
     * ```
     * @see {@link https://faable.com/docs/auth/passwordless | Passwordless Authentication}
     * @category Sign in
     */
    signInWithOtp(data: {
        username: string;
        otp: string;
        audience?: string;
    }): Promise<AuthResponse>;
    /**
     * Finishes a sign-in that a second-factor policy interrupted.
     *
     * Call it with the `mfa_token` from an {@link AuthMfaRequiredError} and the
     * code the user typed — six digits from their authenticator app, or one of
     * their recovery codes.
     *
     * A wrong code does NOT consume the token: prompt again with the same one
     * instead of restarting the sign-in. The token does expire (a few minutes),
     * after which the flow has to start over.
     *
     * @example
     * ```ts
     * const { error } = await auth.signInWithOtp({ username, otp })
     * if (isAuthMfaRequiredError(error)) {
     *   const code = await askUserForTheirCode()
     *   await auth.signInWithMfa({ mfa_token: error.mfa_token, code })
     * }
     * ```
     * @category Sign in
     */
    signInWithMfa(data: {
        mfa_token: string;
        code: string;
        /** Defaults to `otp` — the authenticator app. */
        type?: 'otp' | 'recovery_code';
        audience?: string;
    }): Promise<AuthResponse>;
    /**
     * Starts a passwordless login flow by emailing the user either an OTP code
     * or a magic link.
     *
     * - `type: 'code'` sends a short code the user pastes into your UI; finish
     *   the flow with {@link FaableAuthClient.signInWithOtp}.
     * - `type: 'link'` sends a clickable link that lands on your `redirectUri`
     *   with the tokens already attached, processed by
     *   {@link FaableAuthClient.initialize} on page load.
     *
     * A `code` that was sent is remembered until it is spent: read it back
     * with {@link FaableAuthClient.getPendingPasswordless} when the screen that
     * asked for it is opened again (another tab, an in-app browser that closed
     * while the user read the email). Any sign-in or sign-out on this client
     * forgets it.
     *
     * @param data The user's email and the delivery mechanism.
     *   - `authParams`: profile for the account a code creates (signup), as the
     *     server's `auth_params`.
     *   - `resumeUrl`: a page of yours the code email links back to, for when
     *     it is opened where this browser's storage is not. Must be on one of
     *     the client's registered origins.
     *   - `appState`: kept with the pending code, never sent.
     * @example
     * ```ts
     * await auth.signInWithPasswordless({
     *   email: 'user@example.com',
     *   type: 'code'
     * })
     * ```
     * @see {@link https://faable.com/docs/auth/passwordless | Passwordless Authentication}
     * @category Sign in
     */
    signInWithPasswordless(data: {
        email: string;
        type: 'code' | 'link';
        audience?: string;
        authParams?: Record<string, string>;
        resumeUrl?: string;
        appState?: unknown;
    }): Promise<AuthResult<any>>;
    /**
     * The emailed code this browser is waiting for, or `null`. Written by
     * {@link FaableAuthClient.signInWithPasswordless} (`type: 'code'`) and
     * forgotten on any sign-in or sign-out of this client, and 30 minutes after
     * it was written.
     *
     * @example
     * ```ts
     * const pending = await auth.getPendingPasswordless()
     * if (pending) showCodeStep(pending.email)
     * ```
     * @category Sign in
     */
    getPendingPasswordless(): Promise<PendingPasswordless | null>;
    /**
     * Records a code the user is waiting for that this browser did not ask for
     * — typically one whose email linked back to your `resumeUrl` from another
     * device. Same lifecycle as the one `signInWithPasswordless` writes.
     *
     * @category Sign in
     */
    resumePasswordless(pending: PendingPasswordless): Promise<void>;
    /**
     * Forgets the pending code ("Change email", "Use another account").
     *
     * @category Sign in
     */
    clearPendingPasswordless(): Promise<void>;
    /**
     * Triggers a "change your password" email for a database-connection user.
     *
     * The current session is unaffected — the user clicks the link in the
     * email and completes the reset on the tenant's hosted pages. The promise
     * resolves once the email has been queued.
     *
     * @param params The user's email address.
     * @example
     * ```ts
     * await auth.changePassword({ email: 'user@example.com' })
     * ```
     * @see {@link https://faable.com/docs/auth/connections | Connections}
     * @category Account
     */
    changePassword(params: {
        email: string;
    }): Promise<AuthResult<unknown>>;
    /**
     * Resolves the signed-in user's id from a session. Prefers the userinfo
     * shape (`user.id`) returned by `/me`, falls back to a `sub` claim on the
     * user object, and finally decodes the access token's `sub` — the id is
     * always present there, so this never reports a live session as missing.
     */
    private _resolveUserId;
    /**
     * Starts a verified email change for the currently signed-in user.
     *
     * The user must be authenticated — the call is made with the session's
     * access token, and the auth server only lets a user change their own
     * email. It creates a verification ticket and emails the user; the change
     * is applied only after they click the link, which the server handles and
     * then redirects to `redirect_uri`. The current session is unaffected until
     * then.
     *
     * @param params The new email plus optional verification policy.
     *   - `verification_mode`: `'new_only'` verifies just the new address;
     *     `'old_and_new'` also requires confirming from the old one. When
     *     omitted the account's default policy applies.
     *   - `redirect_uri`: where the server sends the user after they verify.
     * @example
     * ```ts
     * const { data, error } = await auth.changeEmail({
     *   new_email: 'new@example.com',
     *   redirect_uri: 'https://app.example.com/account'
     * })
     * // data: { status: 'verification_sent', ticket_id, verification_mode }
     * ```
     * @see {@link https://faable.com/docs/auth/change-email | Change Email}
     * @category Account
     */
    changeEmail(params: {
        new_email: string;
        verification_mode?: 'new_only' | 'old_and_new';
        redirect_uri?: string;
    }): Promise<AuthResult<unknown>>;
    /**
     * How the signed-in user can sign in: whether they have a password, and
     * which connections (Google, GitHub, the password one…) they are linked to.
     *
     * Use it to choose between "Set a password" and "Change password" on a
     * profile screen. Made with the session's access token; no provider tokens
     * or profile data come back.
     *
     * @example
     * ```ts
     * const { data, error } = await auth.getCredentials()
     * // data: { has_password: false,
     * //         connections: [{ id: 'connection_…', name: 'google', type: 'google_oauth2' }] }
     * ```
     * @see {@link https://faable.com/docs/auth/self-service-account | Self-service account}
     * @category Account
     */
    getCredentials(): Promise<AuthResult<UserCredentials>>;
    /**
     * Sets or changes the signed-in user's password, without leaving the app.
     *
     * - **Changing** an existing password needs `current_password`.
     * - **Setting the first one** (a user who signed up with Google, say) needs
     *   a verified email and a recent sign-in: within 5 minutes and, if the user
     *   has a second factor, one that completed it. Otherwise the error code is
     *   `reauth_required`: send the user through {@link FaableAuthClient.authorize}
     *   with `max_age=0` and call again with the new session.
     *
     * The connection's password policy applies (`password_too_weak`). Every
     * other session of the user is signed out; this one stays. The user gets a
     * security email.
     *
     * @param params
     *   - `password`: the new password.
     *   - `current_password`: required when the user already has one.
     * @example
     * ```ts
     * const { data, error } = await auth.setPassword({ password: newPassword })
     * if (error?.code === 'reauth_required') {
     *   // Back here after a fresh sign-in, then retry.
     *   await auth.authorize({ queryParams: { max_age: '0' } })
     * }
     * // data: { revoked_sessions: 2 }
     * ```
     * @see {@link https://faable.com/docs/auth/self-service-account | Self-service account}
     * @category Account
     */
    setPassword(params: {
        password: string;
        current_password?: string;
    }): Promise<AuthResult<{
        revoked_sessions: number;
    }>>;
    /**
     * Updates the signed-in user's own profile: `name`, `company_name`,
     * `country_iso` and the custom `fields`. Keys left out are not touched.
     *
     * - `country_iso` takes an ISO 3166 code (`ES` or `ESP`) and is stored as
     *   alpha-2; an unknown code fails with `bad_request`.
     * - `fields` are stored in `user_metadata["faable.com/fields"]`. Only the
     *   keys the application declares (`profile_fields` on the client, else on
     *   the tenant) are accepted; any other key, or a value that does not match
     *   its declaration, fails the whole call with `invalid_profile_field`.
     *   Fields are merged by key: keys not named are kept, `value: null`
     *   removes one. The rest of `user_metadata` is untouched.
     *
     * On success the stored session's `user` is updated in place and
     * `USER_UPDATED` fires, so `getSession()` and {@link getProfileField}
     * read the new values right away. The access token's claims follow on
     * the next refresh ({@link FaableAuthClient.refreshSession}).
     *
     * @example
     * ```ts
     * const { data: user, error } = await auth.updateProfile({
     *   name: 'Ada Lovelace',
     *   country_iso: 'GB',
     *   fields: [{ key: 'profile', value: 'teacher' }]
     * })
     * ```
     * @see {@link https://faable.com/docs/auth/self-service-account | Self-service account}
     * @category Account
     */
    updateProfile(params: ProfileUpdate): Promise<AuthResult<User>>;
    /**
     * Sets one custom profile field of the signed-in user, or removes it with
     * `null`. Shorthand for `updateProfile({ fields: [{ key, value }] })`: the
     * key must be declared in the application's `profile_fields`, or the call
     * fails with `invalid_profile_field`. Other fields are kept.
     *
     * @example
     * ```ts
     * const { error } = await auth.updateProfileField('invite_card', 'this-app')
     * ```
     * @see {@link https://faable.com/docs/auth/self-service-account | Self-service account}
     * @category Account
     */
    updateProfileField(key: string, value: string | null): Promise<AuthResult<User>>;
    /**
     * One custom profile field of the signed-in user (from
     * `user_metadata["faable.com/fields"]` of the session's user), or `null`
     * when it is not set or nobody is signed in. Reads the session, no request.
     *
     * @example
     * ```ts
     * const card = await auth.getProfileField('invite_card')
     * ```
     * @see {@link https://faable.com/docs/auth/self-service-account | Self-service account}
     * @category Account
     */
    getProfileField(key: string): Promise<string | null>;
    /**
     * The signed-in user's active sessions — every browser, app and CLI login —
     * newest first, and which one is this. For a "Where you're signed in" list.
     * End the others with `signOut({ scope: 'others' })`.
     *
     * @example
     * ```ts
     * const { data, error } = await auth.listSessions()
     * // data: { results: [{ id: 'session_…', user_agent: '…', ip: '…', … }],
     * //         current_session_id: 'session_…' }
     * ```
     * @see {@link https://faable.com/docs/auth/self-service-account | Self-service account}
     * @category Account
     */
    listSessions(): Promise<AuthResult<UserSessions>>;
    /**
     * Ends every other session of the signed-in user — other browsers, apps
     * and CLI logins — and keeps this one. Same as `signOut({ scope: 'others' })`,
     * plus how many were ended. Their refresh tokens are refused on next use;
     * access tokens already issued keep working until they expire.
     *
     * @example
     * ```ts
     * const { data, error } = await auth.revokeOtherSessions()
     * // data: { revoked: 2 }
     * ```
     * @see {@link https://faable.com/docs/auth/self-service-account | Self-service account}
     * @category Account
     */
    revokeOtherSessions(): Promise<AuthResult<{
        revoked: number;
    }>>;
    /**
     * Unlinks one of the signed-in user's social or enterprise accounts (their
     * Google, GitHub, GitLab…), with the provider tokens it held. Pass the
     * connection id from {@link FaableAuthClient.getCredentials}.
     *
     * Refused with `last_sign_in_method` when it would leave the user with no
     * way to sign in: no password, no account on another connection and no
     * passwordless email sign-in. Offer to set a password
     * ({@link FaableAuthClient.setPassword}) or link another account first.
     * The user's sessions stay.
     *
     * @param connection_id - the connection to unlink (`connection_…`).
     * @example
     * ```ts
     * const { data, error } = await auth.unlinkIdentity('connection_…')
     * if (error?.code === 'last_sign_in_method') {
     *   // "Set a password first"
     * }
     * // data: { unlinked: 1 }
     * ```
     * @see {@link https://faable.com/docs/auth/self-service-account | Self-service account}
     * @category Account
     */
    unlinkIdentity(connection_id: string): Promise<AuthResult<{
        unlinked: number;
    }>>;
    /**
     * Deletes the signed-in user's account: their identities, credentials,
     * second factors and memberships go with it. Permanent — ask the user to
     * confirm first.
     *
     * On success the local session is removed and `SIGNED_OUT` is emitted, as
     * in `signOut({ scope: 'local' })`: the user it belonged to no longer
     * exists. A suspended user is refused (`user_suspended`).
     *
     * @example
     * ```ts
     * const { error } = await auth.deleteAccount()
     * if (!error) router.push('/goodbye')
     * ```
     * @see {@link https://faable.com/docs/auth/self-service-account | Self-service account}
     * @category Account
     */
    deleteAccount(): Promise<AuthResult<null>>;
    /**
     * Runs `fn` with the current session's access token, or reports the
     * session as missing without sending anything.
     */
    private _withAccessToken;
    /**
     * Builds the tenant's `/authorize` URL without redirecting the browser.
     *
     * Useful when you need to render a login link, open the page in a popup,
     * or hand the URL to a different runtime (e.g. a webview). For the
     * everyday "click → redirect" flow use {@link FaableAuthClient.authorize}
     * or {@link FaableAuthClient.signInWithOauthConnection}.
     *
     * The redirect target is resolved with this precedence:
     * `options.redirectTo` → `config.redirectUri` → `window.location.origin`.
     *
     * @returns The fully-qualified authorize URL.
     * @example
     * ```ts
     * const url = auth.buildAuthorizeUrl({
     *   connection: 'google',
     *   redirectTo: 'https://app.example.com/callback'
     * })
     * window.open(url, 'login', 'popup')
     * ```
     * @see {@link https://faable.com/docs/auth/oauth-flows/authorization-code | Authorization Code with PKCE}
     * @category Authorize URLs
     */
    buildAuthorizeUrl(options?: {
        connection?: string;
        redirectTo?: string;
        scope?: string;
        response_type?: string;
        audience?: string;
        /**
         * OIDC `acr_values` — the assurance level this request demands.
         * `urn:faable:loa:2` asks for a login that satisfied a second factor,
         * even when the tenant's policy would not have required one. Combine
         * with `prompt: 'login'` to force a fresh step-up rather than reusing an
         * existing single-factor session.
         */
        acr_values?: string | string[];
        /**
         * The methods the hosted login screen shows for this login — connection
         * ids or names, and `'passkey'`. Each must be one the client already
         * offers; the screen keeps the order configured for the client. Use it
         * to open the same client with fewer options, e.g. only the emailed code:
         * `loginMethods: ['email']`. It narrows the screen; `connection` skips it
         * for a single connection instead, and the two cannot be combined.
         * @see {@link https://faable.com/docs/auth/hosted-login | Hosted Login UI}
         */
        loginMethods?: string | string[];
        /**
         * Extra `/authorize` params merged in as-is — e.g.
         * `{ prompt: 'select_account' }` or `{ prompt: 'login' }` to force
         * account selection / re-authentication even when an SSO session exists.
         */
        queryParams?: {
            [key: string]: string;
        };
    }): string;
    /**
     * Builds the tenant's RP-initiated logout URL
     * (`{domain}/logout?client_id=…`).
     *
     * Navigate the browser to it (top-level, not `fetch`) to end the session and
     * clear the auth server's SSO cookie — the only reliable way to do that from
     * another origin. {@link FaableAuthClient.signOut} does this for you by
     * default; use this helper when you want to drive the navigation yourself.
     *
     * @param options.returnTo Where to send the browser after logout, mapped to
     *   the OIDC `post_logout_redirect_uri`. Must be registered as a logout URL
     *   on the client or the server responds `400`.
     * @param options.idTokenHint The `id_token` of the session being ended
     *   (`id_token_hint`). {@link FaableAuthClient.signOut} passes the stored
     *   one; when driving the navigation yourself, take it from
     *   {@link FaableAuthClient.getSession}.
     * @example
     * ```ts
     * window.location.assign(auth.getLogoutUrl({ returnTo: 'https://app.example.com' }))
     * ```
     * @see {@link https://faable.com/docs/auth/oidc/logout | Logout}
     * @category Authorize URLs
     */
    getLogoutUrl(options?: {
        returnTo?: string;
        idTokenHint?: string;
    }): string;
    /**
     * Redirects the current window to the tenant's `/authorize` endpoint.
     *
     * Fire-and-forget: there is no return value because the browser navigates
     * away. The session lands back on your `redirectUri`, where
     * {@link FaableAuthClient.initialize} consumes it on the next page load.
     * A `code` request from a browser carries a PKCE challenge, whose verifier
     * that landing exchanges the code with — required on a tenant that
     * enforces OAuth 2.1.
     *
     * @example
     * ```ts
     * auth.authorize({
     *   response_type: 'code',
     *   redirectTo: 'https://app.example.com/callback'
     * })
     * ```
     * @see {@link https://faable.com/docs/auth/oauth-flows/authorization-code | Authorization Code with PKCE}
     * @category Authorize URLs
     */
    authorize(options: {
        redirectTo?: string;
        scope?: string;
        response_type: string;
        audience?: string;
        /** See {@link FaableAuthClient.buildAuthorizeUrl}. */
        acr_values?: string | string[];
        /** See {@link FaableAuthClient.buildAuthorizeUrl}. */
        loginMethods?: string | string[];
        queryParams?: {
            [key: string]: string;
        };
    }): Promise<void>;
    /**
     * Sends the user through a fresh login that must satisfy a second factor,
     * regardless of the tenant's policy or of an existing single-factor session.
     *
     * The pattern for a sensitive action — changing payment details, deleting an
     * organisation — where the application wants a stronger proof than the one
     * the session already carries. Read {@link FaableAuthClient.getAal} first:
     * a session that is already `2` needs no step-up.
     *
     * @example
     * ```ts
     * if ((await auth.getAal()) < 2) {
     *   auth.stepUp({ redirectTo: window.location.href })
     *   return
     * }
     * ```
     * @category Authorize URLs
     */
    stepUp(options?: {
        redirectTo?: string;
        scope?: string;
        audience?: string;
    }): Promise<void>;
    private _handleConnectionSignIn;
    /**
     * Best-effort write of a pending login attempt. A storage failure must
     * never break the sign-in itself, so errors are only logged.
     */
    private _saveLoginAttempt;
    /**
     * Promotes the pending login attempt (if any) to the confirmed last-used
     * record. Called from the callback path once a session was established;
     * a login started elsewhere (other tab, other device) leaves no attempt
     * and records nothing.
     */
    private _promoteLoginAttempt;
    /** Best-effort write of the confirmed last-used method cookie. */
    private _recordLastUsedMethod;
    /**
     * Returns the login method the user last *completed* on this browser, or
     * `null` when none was recorded — for login UIs that want to show a
     * PostHog-style "Last used" hint next to the matching sign-in button.
     *
     * A method is recorded only when the login actually establishes a session
     * (the OAuth/password redirect round-trip finishing, or an OTP exchange
     * succeeding); a clicked button whose flow was abandoned or failed leaves
     * no trace. The record survives {@link FaableAuthClient.signOut} on
     * purpose and lives in a dedicated cookie, so it can be shared across
     * subdomains via the `lastUsedCookie.domain` client config.
     *
     * @returns The last confirmed method (`oauth` logins carry the
     *   `connection` / `connection_id` they were started with) or `null`.
     * @example
     * ```ts
     * const last = await auth.getLastUsedLoginMethod()
     * if (last?.method === 'oauth') highlight(last.connection_id)
     * ```
     * @see {@link https://faable.com/docs/auth/connections | Connections}
     * @category Sign in
     */
    getLastUsedLoginMethod(): Promise<LastUsedLoginMethod | null>;
    /**
     * Adopts an externally-provided session into the client.
     *
     * Decodes the access token to find its expiry; refreshes immediately when
     * already expired, otherwise fetches the user info to round-trip the
     * session. Persists the result and broadcasts `SIGNED_IN`. An invalid
     * refresh or access token surfaces as `error` on the returned object.
     *
     * @param currentSession Minimal session shape — an access token and a
     *   refresh token. Other fields are recomputed.
     * @example
     * ```ts
     * // After receiving tokens from a custom server-side handoff
     * await auth.setSession({ access_token, refresh_token })
     * ```
     * @see {@link https://faable.com/docs/auth/oidc/userinfo | UserInfo}
     * @category Sessions
     */
    setSession(currentSession: {
        access_token: string;
        refresh_token: string;
    }): Promise<AuthResponse>;
    /**
     * Returns the session, refreshing it if necessary.
     *
     * The session returned can be `null` if no user is signed in or the last
     * one has logged out.
     *
     * **IMPORTANT:** This method loads values directly from the storage
     * attached to the client. If that storage is based on request cookies (for
     * example, on the server) the values in it may not be authentic and
     * therefore it's strongly advised against using this method and its
     * results in such circumstances — a warning will be emitted when the
     * storage exposes `isServer: true`. Re-fetch the user with a verified
     * call (or verify the access token yourself) before trusting it.
     *
     * @example
     * ```ts
     * const { data, error } = await auth.getSession()
     * if (data.session) console.log(data.session.user)
     * ```
     * @see {@link https://faable.com/docs/auth/oidc/userinfo | UserInfo}
     * @category Sessions
     */
    getSession(): Promise<{
        data: {
            session: Session;
        };
        error: null;
    } | {
        data: {
            session: null;
        };
        error: AuthError;
    } | {
        data: {
            session: null;
        };
        error: null;
    }>;
    /**
     * The claims of the current session's access token, decoded locally — the
     * standard JWT set plus any custom claim the tenant put there (a
     * connection's `claims_mapping`, an Action's
     * `api.accessToken.setCustomClaim`). Refreshes the session first when it
     * has expired, exactly like {@link getSession}, so the claims are always
     * those of a live token; custom claims survive refreshes by design.
     *
     * `claims` is `null` (with no error) when there is no session. The token
     * is decoded, not signature-verified: use the result for UI and routing
     * decisions, never as authorization — that is the resource server's job.
     * Narrow your own claims with the generic parameter.
     *
     * @example
     * ```ts
     * const { data } = await auth.getClaims<{ 'ciapol.com/station_id': string }>()
     * const station = data.claims?.['ciapol.com/station_id']
     * ```
     * @category Sessions
     */
    getClaims<T extends Record<string, unknown> = Record<string, unknown>>(): Promise<{
        data: {
            claims: JwtClaims & T;
            session: Session;
        };
        error: null;
    } | {
        data: {
            claims: null;
            session: null;
        };
        error: AuthError | null;
    }>;
    /**
     * One claim of the current session's access token, or `null` when there is
     * no session or the claim is absent. Sugar over {@link getClaims}.
     *
     * @example
     * ```ts
     * const station = await auth.getClaim<string>('ciapol.com/station_id')
     * ```
     * @category Sessions
     */
    getClaim<T = unknown>(name: string): Promise<T | null>;
    /**
     * Authenticator Assurance Level of the current session: `2` when it
     * satisfied a second factor (or a passkey that verified the user did both
     * at once), `1` for a single factor, `0` when there is no session.
     *
     * Read locally from the access token's `acr` claim — no network call — so it
     * is cheap enough to gate a render on.
     *
     * @example
     * ```ts
     * if ((await auth.getAal()) < 2) auth.stepUp()
     * ```
     * @category Session
     */
    getAal(): Promise<0 | 1 | 2>;
    /**
     * Did the current session authenticate with this method?
     *
     * Values follow RFC 8176 as the server emits them: `pwd`, `otp`, `hwk` for
     * a hardware key, `federated` for a social login, and `mfa` once a second
     * factor was satisfied.
     *
     * @example
     * ```ts
     * const usedPasskey = await auth.hasAmr('hwk')
     * ```
     * @category Session
     */
    hasAmr(method: string): Promise<boolean>;
    /**
     * Does the current session's access token carry these permissions (all of
     * them)? Read from the `permissions` claim, which the API emits with the
     * `access_token_authz` dialect; with RBAC on the API, a user token carries
     * the permissions you requested as scopes that the user's roles grant.
     *
     * Decoded locally, not verified: use it to show or hide UI. Your API must
     * check the token itself.
     *
     * @example
     * ```ts
     * if (await auth.hasPermission('invites:write')) showInviteButton()
     * ```
     * @category Sessions
     */
    hasPermission(permission: string | string[]): Promise<boolean>;
    /**
     * Does the current session's access token carry these roles (all of them)?
     * Read from the `roles` claim, present when the API enables
     * `include_roles_in_access_token`. Same caveat as {@link hasPermission}.
     *
     * @example
     * ```ts
     * const isAdmin = await auth.hasRole('admin')
     * ```
     * @category Sessions
     */
    hasRole(role: string | string[]): Promise<boolean>;
    /**
     * Error the auth server returned via redirect on the current page load
     * (`?error=access_denied&error_description=...`, RFC 6749 §4.1.2.1), or
     * `null` when the page wasn't reached through a failed auth round-trip.
     *
     * Consume-once: the first read clears it (and the params were already
     * stripped from the URL at initialization), so a later router navigation
     * can't re-show a stale failure. Exists because the promise returned by
     * {@link signInWithOauthConnection} dies with the top-level navigation —
     * this is the only place the app can learn WHY the round-trip failed
     * (e.g. an action deny like "Signups from this network are currently
     * restricted").
     *
     * @example
     * ```ts
     * const redirectError = await auth.getRedirectError()
     * if (redirectError) showAlert(redirectError.error_description)
     * ```
     * @category Sessions
     */
    getRedirectError(): Promise<RedirectError | null>;
    /**
     * The error of an `?error=` redirect, with what the PKCE record of the
     * round trip that failed remembers: connection, link mode, `appState`,
     * `returnTo`. The record is spent here — the code it was waiting for is
     * never coming. Best-effort: without a record (another browser started it,
     * it expired, storage is blocked) the bare error is still returned.
     */
    private _redirectErrorWithAttempt;
    /**
     * Why the SDK last terminated the session on its own (a refresh rejected
     * by the server — e.g. `code: 'user_suspended'`, a revoked grant), or
     * `null` when the last sign-out was voluntary or there was none.
     *
     * Consume-once, like {@link getRedirectError}: the first read clears it so
     * a later visit to the login page can't re-show a stale banner. Persisted
     * in storage (not memory) because the terminating tab usually navigates
     * away — the login page that renders the reason is a fresh document.
     *
     * @example
     * ```ts
     * const reason = await auth.getSignOutReason()
     * if (reason?.code === 'user_suspended') showSuspendedPanel()
     * ```
     * @category Sessions
     */
    getSignOutReason(): Promise<SignOutReason | null>;
    /**
     * Persist the reason for an SDK-initiated session termination. Voluntary
     * {@link signOut} never writes this — only terminal refresh failures do.
     */
    private _stashSignOutReason;
    /**
     * Use instead of {@link #getSession} inside the library. It is
     * semantically usually what you want, as getting a session involves some
     * processing afterwards that requires only one client operating on the
     * session at once across multiple tabs or processes.
     */
    private _useSession;
    /**
     * NEVER USE DIRECTLY!
     *
     * Always use {@link #_useSession}.
     */
    private __loadSession;
    private _removeSession;
    protected _setSession(currentSession: {
        access_token: string;
        refresh_token: string;
    }): Promise<AuthResponse>;
    /**
     * set currentSession and currentUser
     * process to _startAutoRefreshToken if possible
     */
    private _saveSession;
    /**
     * Merges `user` into the stored session and tells subscribers
     * (`USER_UPDATED`): what the account routes return is the user as it is now.
     */
    private _updateSessionUser;
    private _getUser;
    private _callRefreshToken;
    /**
     * Generates a new JWT.
     * @param refreshToken A valid refresh token that was returned on login.
     */
    private _refreshAccessToken;
    /**
     * Posts an auth event to the other tabs of this `storageKey` and to NO
     * subscriber of this document. For the one case where this document must
     * not react: it is navigating away (see the redirect path of `_signOut`).
     */
    private _notifyOtherTabs;
    private _notifyAllSubscribers;
    /**
     * Signs the user out and clears the session from storage.
     *
     * In a browser context this removes the persisted session and broadcasts a
     * `SIGNED_OUT` event to every tab listening on the same `storageKey`. The
     * access token JWT itself remains valid until its `exp` — keep that
     * expiry short.
     *
     * **By default (`'app'` scope) it signs the user out of this app only**: its
     * refresh token is revoked at the auth server (RFC 7009) and its storage
     * cleared, with no navigation. The tenant's SSO session stays, so the
     * user's other apps on the same tenant keep theirs, and the next sign-in
     * here comes back without asking.
     *
     * To end the SSO session too, pass `{ scope: 'global' }`: in a browser the
     * page navigates to the auth server's `/logout` (a cross-origin `fetch`
     * cannot clear that cookie) and returns to `returnTo` if given; the
     * returned promise does not resolve on that path, and this document's
     * `onAuthStateChange` listeners are not told `SIGNED_OUT` (other tabs
     * are): the page is leaving, and a guard reacting to the event would
     * start a second navigation racing the first. `{ scope: 'global',
     * redirect: false }` keeps the legacy fetch-only behaviour, or use
     * {@link FaableAuthClient.getLogoutUrl} to drive the navigation yourself.
     *
     * Scopes:
     * - `'app'` (default) — this app only, as above. The revoke is best-effort:
     *   the local sign-out happens whatever it answers.
     * - `'global'` — ends **this browser's** session at the auth server: every
     *   refresh token issued in it is refused from then on, in every app of the
     *   tenant, and in a browser the page navigates to `/logout` to clear the
     *   SSO cookie. Sessions on other devices are untouched — that is what
     *   `'others'` is for.
     * - `'local'` — only clear this client's storage. Nothing is sent to the
     *   server: the SSO session and its refresh tokens stay valid (no redirect).
     * - `'others'` — `POST /me/sessions/revoke-others`: ends every session of
     *   the user **except this one**. The local session stays, no `SIGNED_OUT`
     *   event is fired and there is no redirect. Needs a live access token.
     *
     * @example
     * ```ts
     * await auth.signOut() // this app only; the user's other apps stay signed in
     * await auth.signOut({ scope: 'global' }) // + the SSO session, via /logout
     * await auth.signOut({ scope: 'global', returnTo: 'https://app.example.com/bye' })
     * await auth.signOut({ scope: 'local' }) // only this device's storage
     * await auth.signOut({ scope: 'others' }) // every other device, stay signed in
     * ```
     * @see {@link https://faable.com/docs/auth/oidc/logout | Logout}
     * @category Sign out
     */
    signOut(options?: SignOut): Promise<{
        error: AuthError | null;
    }>;
    protected _signOut({ scope, redirect, returnTo }?: SignOut): Promise<{
        error: AuthError | null;
    }>;
    /**
     * Subscribes to auth-state changes for this client.
     *
     * The callback fires for `INITIAL_SESSION` once shortly after subscribing
     * (so consumers don't have to special-case "no event yet"), and then for
     * every `SIGNED_IN`, `SIGNED_OUT`, `TOKEN_REFRESHED`, `PASSWORD_RECOVERY`,
     * and `USER_UPDATED` event. Events are broadcast across tabs through
     * `BroadcastChannel`, so a sign-in or sign-out in one tab reaches every
     * other tab using the same `storageKey`.
     *
     * @param callback Invoked with the event name and the new session (or
     *   `null` on `SIGNED_OUT`). Can return a promise — the SDK awaits it.
     * @returns `{ data: { subscription } }` — call `subscription.unsubscribe()`
     *   to stop listening.
     * @example
     * ```ts
     * const { data: { subscription } } = auth.onAuthStateChange((event, session) => {
     *   if (event === 'SIGNED_IN') console.log('Welcome', session?.user.email)
     * })
     * // later
     * subscription.unsubscribe()
     * ```
     * @see {@link https://faable.com/docs/auth/get-started | Get Started with Faable Auth}
     * @category Sessions
     */
    onAuthStateChange(callback: (event: AuthChangeEvent, session: Session | null) => void | Promise<void>): {
        data: {
            subscription: Subscription;
        };
    };
    private _emitInitialSession;
    /**
     * Forces a new session by exchanging a refresh token regardless of expiry.
     *
     * Normally the SDK handles refresh transparently via the auto-refresh
     * ticker; call this only when you need to force an immediate refresh —
     * e.g. right after a server-side action that changed the user's claims.
     * Omit `currentSession` to reuse whatever {@link FaableAuthClient.getSession}
     * returns.
     *
     * @param currentSession Optional session shape carrying the refresh token
     *   to exchange. When passed it must include `refresh_token`.
     * @example
     * ```ts
     * const { data, error } = await auth.refreshSession()
     * ```
     * @see {@link https://faable.com/docs/auth/oauth-flows/refresh-token | Refresh Token}
     * @category Sessions
     */
    refreshSession(currentSession?: {
        refresh_token: string;
    }): Promise<AuthResponse>;
    protected _refreshSession(currentSession?: {
        refresh_token: string;
    }): Promise<AuthResponse>;
    /**
     * A live access token without showing a login screen — or the reason there
     * cannot be one.
     *
     * 1. **Refresh first.** The stored refresh token is exchanged at
     *    `/oauth/token` (no navigation). This is the everyday path.
     * 2. **Then `prompt=none`, as a top-level navigation.** When the refresh
     *    is refused — no session, or `invalid_grant` because the session was
     *    revoked: a sign-out on another device, an admin revoke, a
     *    back-channel logout — the SDK sends the browser through
     *    `/authorize?prompt=none`. The auth server signs the user back in from
     *    its SSO cookie without a screen, and the page lands on `redirectTo`
     *    with the user's location in `returnTo` (see
     *    {@link FaableAuthClient.initialize}). On this path the promise **never
     *    resolves**: the page is navigating away.
     *
     * There is no hidden iframe on purpose: third-party cookie blocking makes an
     * iframe to the auth domain unreliable in every major browser, so the silent
     * round-trip is a real navigation the user does not see.
     *
     * When the SSO session is gone too, the server comes back with
     * `?error=login_required`. {@link initialize} keeps that for one
     * {@link getRedirectError} read, and a further `getTokenSilently()` on the
     * same page load resolves with an `AuthLoginRequiredError` instead of
     * navigating again — no loops. A network failure or a 5xx during the
     * refresh is not a refusal: it comes back as the retryable error, and the
     * session is kept.
     *
     * @example
     * ```ts
     * const { data, error } = await auth.getTokenSilently()
     * if (error) {
     *   if (error.code === 'login_required') auth.authorize({ response_type: 'code' })
     *   return
     * }
     * fetch('/api/me', { headers: { Authorization: `Bearer ${data.access_token}` } })
     * ```
     * @category Sessions
     */
    getTokenSilently(options?: GetTokenSilently): Promise<{
        data: {
            access_token: string;
            session: Session;
        };
        error: null;
    } | {
        data: null;
        error: AuthError;
    }>;
}
