@feelflow/ffid-sdk 5.12.0 → 5.13.0

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.
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDCheckServiceAccessParams, h as FFIDServiceAccessDecision, i as FFIDProfileCallOptions, j as FFIDUserProfile, k as FFIDUpdateUserProfileRequest, l as FFIDAnalyticsConfig, m as FFIDVerifyAccessTokenOptions, n as FFIDOAuthUserInfo, o as FFIDInquiryCreateParams, p as FFIDInquiryCreateResponse, q as FFIDAuthMode, r as FFIDLogger, s as FFIDCacheAdapter, t as FFIDUser, u as FFIDOrganization, v as FFIDSubscription, w as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, x as FFIDOAuthUserInfoSubscription, y as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, z as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, B as FFIDAnnouncementsLogger } from './index-DqsWKU16.cjs';
2
- export { C as Announcement, D as AnnouncementStatus, G as AnnouncementType, H as EFFECTIVE_SUBSCRIPTION_STATUSES, I as FFIDAnnouncementBadge, J as FFIDAnnouncementList, K as FFIDAnnouncementsError, M as FFIDAnnouncementsErrorCode, N as FFIDAnnouncementsServerResponse, O as FFIDCacheConfig, P as FFIDContextValue, Q as FFIDInquiryCategory, R as FFIDInquiryCategorySite2026, S as FFIDInquiryForm, T as FFIDInquiryFormCategoryItem, U as FFIDInquiryFormClassNames, V as FFIDInquiryFormLegalLayout, W as FFIDInquiryFormOrganization, X as FFIDInquiryFormPlaceholderContext, Y as FFIDInquiryFormPrefill, Z as FFIDInquiryFormProps, _ as FFIDInquiryFormSubmitData, $ as FFIDInquiryFormSubmitResult, a0 as FFIDJwtClaims, a1 as FFIDLoginButton, a2 as FFIDOAuthTokenResponse, a3 as FFIDOAuthUserInfoMemberRole, a4 as FFIDOrganizationSwitcher, a5 as FFIDRedirectErrorCode, a6 as FFIDSeatModel, a7 as FFIDServiceAccessDenialReason, a8 as FFIDServiceAccessFailPolicy, a9 as FFIDSubscriptionBadge, aa as FFIDTokenIntrospectionResponse, ab as FFIDUserMenu, ac as FFID_INQUIRY_CATEGORIES, ad as FFID_INQUIRY_CATEGORIES_SITE_2026, ae as UseFFIDAnnouncementsOptions, af as UseFFIDAnnouncementsReturn, ag as isFFIDInquiryCategorySite2026, ah as useFFIDAnnouncements } from './index-DqsWKU16.cjs';
1
+ import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDCheckServiceAccessParams, h as FFIDServiceAccessDecision, i as FFIDProfileCallOptions, j as FFIDUserProfile, k as FFIDUpdateUserProfileRequest, l as FFIDAnalyticsConfig, m as FFIDVerifyAccessTokenOptions, n as FFIDOAuthUserInfo, o as FFIDInquiryCreateParams, p as FFIDInquiryCreateResponse, q as FFIDAuthMode, r as FFIDLogger, s as FFIDCacheAdapter, t as FFIDUser, u as FFIDOrganization, v as FFIDSubscription, w as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, x as FFIDOAuthUserInfoSubscription, y as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, z as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, B as FFIDAnnouncementsLogger } from './index-C6dnexXf.cjs';
2
+ export { C as Announcement, D as AnnouncementStatus, G as AnnouncementType, H as EFFECTIVE_SUBSCRIPTION_STATUSES, I as FFIDAnnouncementBadge, J as FFIDAnnouncementList, K as FFIDAnnouncementsError, M as FFIDAnnouncementsErrorCode, N as FFIDAnnouncementsServerResponse, O as FFIDCacheConfig, P as FFIDContextValue, Q as FFIDInquiryCategory, R as FFIDInquiryCategorySite2026, S as FFIDInquiryForm, T as FFIDInquiryFormCategoryItem, U as FFIDInquiryFormClassNames, V as FFIDInquiryFormLegalLayout, W as FFIDInquiryFormOrganization, X as FFIDInquiryFormPlaceholderContext, Y as FFIDInquiryFormPrefill, Z as FFIDInquiryFormProps, _ as FFIDInquiryFormSubmitData, $ as FFIDInquiryFormSubmitResult, a0 as FFIDJwtClaims, a1 as FFIDLoginButton, a2 as FFIDOAuthTokenResponse, a3 as FFIDOAuthUserInfoMemberRole, a4 as FFIDOrganizationSwitcher, a5 as FFIDRedirectErrorCode, a6 as FFIDSeatModel, a7 as FFIDServiceAccessDenialReason, a8 as FFIDServiceAccessFailPolicy, a9 as FFIDSubscriptionBadge, aa as FFIDTokenIntrospectionResponse, ab as FFIDUserMenu, ac as FFID_INQUIRY_CATEGORIES, ad as FFID_INQUIRY_CATEGORIES_SITE_2026, ae as UseFFIDAnnouncementsOptions, af as UseFFIDAnnouncementsReturn, ag as isFFIDInquiryCategorySite2026, ah as useFFIDAnnouncements } from './index-C6dnexXf.cjs';
3
3
  export { A as ALL_DENIED_EXCEPT_NECESSARY, i as CONSENT_COOKIE_NAME, j as CONSENT_DISMISSAL_TIMESTAMP_KEY, l as COOKIE_VERSION, D as DEFAULT_CONSENT_ERROR_MESSAGES, o as FFIDAnalyticsProvider, p as FFIDAnalyticsProviderProps, c as FFIDConsentCategories, r as FFIDConsentCategoryCode, e as FFIDConsentCategoryMetadata, w as FFIDConsentError, x as FFIDConsentErrorCode, y as FFIDConsentMergeStrategy, B as FFIDConsentMergeWarning, E as FFIDConsentMergeWarningEvent, F as FFIDConsentResult, I as FFIDConsentSource, a as FFIDConsentState, d as FFIDConsentSyncResult, M as FFIDCookieBanner, N as FFIDCookieBannerClassNames, O as FFIDCookieBannerProps, Q as FFIDCookieLink, R as FFIDCookieLinkProps, f as FFIDCookiePolicy, T as FFIDCookieSettings, U as FFIDCookieSettingsClassNames, V as FFIDCookieSettingsProps, _ as FFID_CONSENT_ERROR_CODES, ae as UseFFIDConsentPreferencesReturn, af as UseFFIDConsentReturn, ag as clearConsentDismissalTimestamp, aj as decodeConsentCookie, al as encodeConsentCookie, an as readConsentCookie, ao as readConsentDismissalTimestamp, aq as useFFIDConsent, ar as useFFIDConsentPreferences, as as writeConsentCookie, at as writeConsentDismissalTimestamp } from './FFIDCookieLink-D1WwE_ZO.cjs';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import { ReactNode, ComponentType, FC } from 'react';
@@ -122,6 +122,35 @@ declare function storeCodeVerifier(verifier: string, logger?: PKCELogger): boole
122
122
  */
123
123
  declare function retrieveCodeVerifier(logger?: PKCELogger): string | null;
124
124
 
125
+ /** Logger interface matching FFIDLogger for optional warning output */
126
+ interface StateLogger {
127
+ warn: (...args: unknown[]) => void;
128
+ }
129
+ /**
130
+ * Store the OAuth `state` for later retrieval.
131
+ *
132
+ * Writes to both sessionStorage (primary) and localStorage (fallback for iOS
133
+ * WebKit sessionStorage eviction during external OAuth bounces). Returns true
134
+ * if at least one write succeeded.
135
+ *
136
+ * @param state - The OAuth state value to store
137
+ * @param logger - Optional logger for warning on storage failure
138
+ * @returns true if stored in at least one storage, false otherwise
139
+ */
140
+ declare function storeState(state: string, logger?: StateLogger): boolean;
141
+ /**
142
+ * Retrieve and remove the OAuth `state`.
143
+ *
144
+ * Reads from sessionStorage first, falls back to localStorage (with 5-minute TTL).
145
+ * Removes from all storages after retrieval (one-time use). Returns null if no
146
+ * state is stored, the fallback is stale (>5 min), or storage is unavailable.
147
+ *
148
+ * @param logger - Optional logger for warning on storage failure
149
+ */
150
+ declare function retrieveState(logger?: StateLogger): string | null;
151
+
152
+ declare function cleanupStateStorage(logger?: StateLogger): void;
153
+
125
154
  /**
126
155
  * Billing checkout / portal session types.
127
156
  *
@@ -716,6 +745,25 @@ interface ContractWizardSubscriptionOptions {
716
745
  organizationId?: string;
717
746
  }
718
747
 
748
+ /** OAuth token operations - exchangeCodeForTokens / refreshAccessToken / signOutToken */
749
+
750
+ /**
751
+ * Optional OAuth `state` validation for {@link exchangeCodeForTokens}.
752
+ *
753
+ * If a `state` is supplied on EITHER side — `expectedState` (the value persisted
754
+ * at `redirectToAuthorize`) or `actualState` (the value returned on the callback
755
+ * URL) — both must be present and equal before any token exchange. A mismatch
756
+ * OR an omitted counterpart fails closed (no exchange) to defend against CSRF
757
+ * (RFC 6749 §10.12 / #3841). Validation is skipped only when BOTH are omitted
758
+ * (backward compatible — callers that don't opt in are unaffected).
759
+ */
760
+ interface ExchangeCodeForTokensOptions {
761
+ /** Stored state from `redirectToAuthorize` (e.g. `retrieveState()`) */
762
+ expectedState?: string;
763
+ /** State returned on the OAuth callback URL */
764
+ actualState?: string;
765
+ }
766
+
719
767
  /** Redirect and URL generation - redirectToLogin / redirectToAuthorize / redirectToLogout / getLoginUrl / getSignupUrl / getLogoutUrl */
720
768
 
721
769
  /**
@@ -755,7 +803,7 @@ declare function createFFIDClient(config: FFIDConfig): {
755
803
  getLogoutUrl: (postLogoutRedirectUri?: string) => string;
756
804
  getSignupUrl: (redirectUrl?: string) => string;
757
805
  createError: (code: string, message: string) => FFIDError;
758
- exchangeCodeForTokens: (code: string, codeVerifier?: string) => Promise<FFIDApiResponse<void>>;
806
+ exchangeCodeForTokens: (code: string, codeVerifier?: string, opts?: ExchangeCodeForTokensOptions) => Promise<FFIDApiResponse<void>>;
759
807
  refreshAccessToken: () => Promise<FFIDApiResponse<void>>;
760
808
  checkSubscription: (params: {
761
809
  userId?: string;
@@ -857,6 +905,52 @@ declare class FFIDSDKError extends Error {
857
905
  constructor(code: string, message: string);
858
906
  }
859
907
 
908
+ /**
909
+ * OAuth redirect callback handler
910
+ *
911
+ * `handleRedirectCallback` is the convenience counterpart to
912
+ * `redirectToAuthorize`: it reads `code` + `state` from the callback URL,
913
+ * validates the OAuth `state` against the value persisted at authorize time
914
+ * (CSRF protection, RFC 6749 §10.12), retrieves the PKCE verifier, exchanges
915
+ * the code for tokens, and cleans the params out of the URL on success.
916
+ */
917
+
918
+ /**
919
+ * Minimal client surface required by {@link handleRedirectCallback}.
920
+ * A full {@link FFIDClient} satisfies this structurally.
921
+ */
922
+ type HandleRedirectCallbackClient = Pick<FFIDClient, 'exchangeCodeForTokens' | 'createError' | 'logger'>;
923
+ /** Options for {@link handleRedirectCallback} */
924
+ interface HandleRedirectCallbackOptions {
925
+ /**
926
+ * Callback URL (or query string) to read `code` / `state` from. Accepts an
927
+ * absolute URL, a relative URL, or a bare query string. Defaults to
928
+ * `window.location.search` in the browser.
929
+ */
930
+ url?: string;
931
+ }
932
+ /**
933
+ * Complete an OAuth authorization-code redirect.
934
+ *
935
+ * Behavior:
936
+ * 1. Reads `code` + `state` from `options.url ?? window.location.search`.
937
+ * 2. CSRF guard: if a `state` exists on EITHER side (a stored state from
938
+ * authorize OR a `state` on the callback URL), the two MUST match — mismatch,
939
+ * a missing stored state, or an **omitted** callback `state` all **fail closed**
940
+ * (returns an error, performs no exchange). Validation is skipped ONLY when
941
+ * neither side has any state (a genuine no-state flow). Omitting the callback
942
+ * `state` does NOT bypass the check (#3841).
943
+ * 3. Retrieves the PKCE verifier and exchanges the code for tokens.
944
+ * 4. On success, removes `code` + `state` from the browser URL.
945
+ *
946
+ * SSR-safe: when there is no `window` and no `options.url`, no exchange is
947
+ * attempted and an error result is returned.
948
+ *
949
+ * @param client - FFID client (or any object exposing exchangeCodeForTokens / createError / logger)
950
+ * @param options - Optional callback URL override
951
+ */
952
+ declare function handleRedirectCallback(client: HandleRedirectCallbackClient, options?: HandleRedirectCallbackOptions): Promise<FFIDApiResponse<void>>;
953
+
860
954
  /**
861
955
  * Redirect URI normalization (SDK copy)
862
956
  *
@@ -1565,4 +1659,4 @@ declare function createInquiryMethods(deps: InquiryMethodsDeps): {
1565
1659
  };
1566
1660
  type FFIDInquiryClient = ReturnType<typeof createInquiryMethods>;
1567
1661
 
1568
- export { ACCESS_GRANTING_EFFECTIVE_STATUSES, AnnouncementListResponse, BLOCKING_EFFECTIVE_STATUSES, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EffectiveSubscriptionStatus, type FFIDAddMemberParams, type FFIDAddMemberRequest, type FFIDAddMemberResponse, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDAssignableMemberRole, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckServiceAccessParams, type FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, type FFIDCreateCheckoutParams, type FFIDCreatePortalParams, FFIDError, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, type FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, type FFIDMemberRole, type FFIDMemberStatus, type FFIDNewsletterBodySource, type FFIDNewsletterCampaignStatus, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterDispatchParams, type FFIDNewsletterDispatchResponse, type FFIDNewsletterSegment, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOAuthUserInfoSubscription, FFIDOrganization, type FFIDOrganizationMember, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, type FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, type FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, FFIDServiceAccessDecision, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, type FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_DISPATCH_MAX_RECIPIENTS, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, hasAccessFromUserinfo, isBlockedFromUserinfo, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
1662
+ export { ACCESS_GRANTING_EFFECTIVE_STATUSES, AnnouncementListResponse, BLOCKING_EFFECTIVE_STATUSES, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EffectiveSubscriptionStatus, type ExchangeCodeForTokensOptions, type FFIDAddMemberParams, type FFIDAddMemberRequest, type FFIDAddMemberResponse, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDAssignableMemberRole, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckServiceAccessParams, type FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, type FFIDCreateCheckoutParams, type FFIDCreatePortalParams, FFIDError, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, type FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, type FFIDMemberRole, type FFIDMemberStatus, type FFIDNewsletterBodySource, type FFIDNewsletterCampaignStatus, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterDispatchParams, type FFIDNewsletterDispatchResponse, type FFIDNewsletterSegment, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOAuthUserInfoSubscription, FFIDOrganization, type FFIDOrganizationMember, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, type FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, type FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, FFIDServiceAccessDecision, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, type FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_DISPATCH_MAX_RECIPIENTS, FFID_NEWSLETTER_TYPES, type HandleRedirectCallbackClient, type HandleRedirectCallbackOptions, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, cleanupStateStorage as clearState, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, handleRedirectCallback, hasAccessFromUserinfo, isBlockedFromUserinfo, normalizeRedirectUri, retrieveCodeVerifier, retrieveState, storeCodeVerifier, storeState, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDCheckServiceAccessParams, h as FFIDServiceAccessDecision, i as FFIDProfileCallOptions, j as FFIDUserProfile, k as FFIDUpdateUserProfileRequest, l as FFIDAnalyticsConfig, m as FFIDVerifyAccessTokenOptions, n as FFIDOAuthUserInfo, o as FFIDInquiryCreateParams, p as FFIDInquiryCreateResponse, q as FFIDAuthMode, r as FFIDLogger, s as FFIDCacheAdapter, t as FFIDUser, u as FFIDOrganization, v as FFIDSubscription, w as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, x as FFIDOAuthUserInfoSubscription, y as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, z as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, B as FFIDAnnouncementsLogger } from './index-DqsWKU16.js';
2
- export { C as Announcement, D as AnnouncementStatus, G as AnnouncementType, H as EFFECTIVE_SUBSCRIPTION_STATUSES, I as FFIDAnnouncementBadge, J as FFIDAnnouncementList, K as FFIDAnnouncementsError, M as FFIDAnnouncementsErrorCode, N as FFIDAnnouncementsServerResponse, O as FFIDCacheConfig, P as FFIDContextValue, Q as FFIDInquiryCategory, R as FFIDInquiryCategorySite2026, S as FFIDInquiryForm, T as FFIDInquiryFormCategoryItem, U as FFIDInquiryFormClassNames, V as FFIDInquiryFormLegalLayout, W as FFIDInquiryFormOrganization, X as FFIDInquiryFormPlaceholderContext, Y as FFIDInquiryFormPrefill, Z as FFIDInquiryFormProps, _ as FFIDInquiryFormSubmitData, $ as FFIDInquiryFormSubmitResult, a0 as FFIDJwtClaims, a1 as FFIDLoginButton, a2 as FFIDOAuthTokenResponse, a3 as FFIDOAuthUserInfoMemberRole, a4 as FFIDOrganizationSwitcher, a5 as FFIDRedirectErrorCode, a6 as FFIDSeatModel, a7 as FFIDServiceAccessDenialReason, a8 as FFIDServiceAccessFailPolicy, a9 as FFIDSubscriptionBadge, aa as FFIDTokenIntrospectionResponse, ab as FFIDUserMenu, ac as FFID_INQUIRY_CATEGORIES, ad as FFID_INQUIRY_CATEGORIES_SITE_2026, ae as UseFFIDAnnouncementsOptions, af as UseFFIDAnnouncementsReturn, ag as isFFIDInquiryCategorySite2026, ah as useFFIDAnnouncements } from './index-DqsWKU16.js';
1
+ import { F as FFIDSubscriptionStatus, a as FFIDConfig, b as FFIDApiResponse, c as FFIDSessionResponse, d as FFIDRedirectResult, e as FFIDError, f as FFIDSubscriptionCheckResponse, g as FFIDCheckServiceAccessParams, h as FFIDServiceAccessDecision, i as FFIDProfileCallOptions, j as FFIDUserProfile, k as FFIDUpdateUserProfileRequest, l as FFIDAnalyticsConfig, m as FFIDVerifyAccessTokenOptions, n as FFIDOAuthUserInfo, o as FFIDInquiryCreateParams, p as FFIDInquiryCreateResponse, q as FFIDAuthMode, r as FFIDLogger, s as FFIDCacheAdapter, t as FFIDUser, u as FFIDOrganization, v as FFIDSubscription, w as FFIDSubscriptionContextValue, E as EffectiveSubscriptionStatus, x as FFIDOAuthUserInfoSubscription, y as FFIDAnnouncementsClientConfig, L as ListAnnouncementsOptions, z as FFIDAnnouncementsApiResponse, A as AnnouncementListResponse, B as FFIDAnnouncementsLogger } from './index-C6dnexXf.js';
2
+ export { C as Announcement, D as AnnouncementStatus, G as AnnouncementType, H as EFFECTIVE_SUBSCRIPTION_STATUSES, I as FFIDAnnouncementBadge, J as FFIDAnnouncementList, K as FFIDAnnouncementsError, M as FFIDAnnouncementsErrorCode, N as FFIDAnnouncementsServerResponse, O as FFIDCacheConfig, P as FFIDContextValue, Q as FFIDInquiryCategory, R as FFIDInquiryCategorySite2026, S as FFIDInquiryForm, T as FFIDInquiryFormCategoryItem, U as FFIDInquiryFormClassNames, V as FFIDInquiryFormLegalLayout, W as FFIDInquiryFormOrganization, X as FFIDInquiryFormPlaceholderContext, Y as FFIDInquiryFormPrefill, Z as FFIDInquiryFormProps, _ as FFIDInquiryFormSubmitData, $ as FFIDInquiryFormSubmitResult, a0 as FFIDJwtClaims, a1 as FFIDLoginButton, a2 as FFIDOAuthTokenResponse, a3 as FFIDOAuthUserInfoMemberRole, a4 as FFIDOrganizationSwitcher, a5 as FFIDRedirectErrorCode, a6 as FFIDSeatModel, a7 as FFIDServiceAccessDenialReason, a8 as FFIDServiceAccessFailPolicy, a9 as FFIDSubscriptionBadge, aa as FFIDTokenIntrospectionResponse, ab as FFIDUserMenu, ac as FFID_INQUIRY_CATEGORIES, ad as FFID_INQUIRY_CATEGORIES_SITE_2026, ae as UseFFIDAnnouncementsOptions, af as UseFFIDAnnouncementsReturn, ag as isFFIDInquiryCategorySite2026, ah as useFFIDAnnouncements } from './index-C6dnexXf.js';
3
3
  export { A as ALL_DENIED_EXCEPT_NECESSARY, i as CONSENT_COOKIE_NAME, j as CONSENT_DISMISSAL_TIMESTAMP_KEY, l as COOKIE_VERSION, D as DEFAULT_CONSENT_ERROR_MESSAGES, o as FFIDAnalyticsProvider, p as FFIDAnalyticsProviderProps, c as FFIDConsentCategories, r as FFIDConsentCategoryCode, e as FFIDConsentCategoryMetadata, w as FFIDConsentError, x as FFIDConsentErrorCode, y as FFIDConsentMergeStrategy, B as FFIDConsentMergeWarning, E as FFIDConsentMergeWarningEvent, F as FFIDConsentResult, I as FFIDConsentSource, a as FFIDConsentState, d as FFIDConsentSyncResult, M as FFIDCookieBanner, N as FFIDCookieBannerClassNames, O as FFIDCookieBannerProps, Q as FFIDCookieLink, R as FFIDCookieLinkProps, f as FFIDCookiePolicy, T as FFIDCookieSettings, U as FFIDCookieSettingsClassNames, V as FFIDCookieSettingsProps, _ as FFID_CONSENT_ERROR_CODES, ae as UseFFIDConsentPreferencesReturn, af as UseFFIDConsentReturn, ag as clearConsentDismissalTimestamp, aj as decodeConsentCookie, al as encodeConsentCookie, an as readConsentCookie, ao as readConsentDismissalTimestamp, aq as useFFIDConsent, ar as useFFIDConsentPreferences, as as writeConsentCookie, at as writeConsentDismissalTimestamp } from './FFIDCookieLink-D1WwE_ZO.js';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
  import { ReactNode, ComponentType, FC } from 'react';
@@ -122,6 +122,35 @@ declare function storeCodeVerifier(verifier: string, logger?: PKCELogger): boole
122
122
  */
123
123
  declare function retrieveCodeVerifier(logger?: PKCELogger): string | null;
124
124
 
125
+ /** Logger interface matching FFIDLogger for optional warning output */
126
+ interface StateLogger {
127
+ warn: (...args: unknown[]) => void;
128
+ }
129
+ /**
130
+ * Store the OAuth `state` for later retrieval.
131
+ *
132
+ * Writes to both sessionStorage (primary) and localStorage (fallback for iOS
133
+ * WebKit sessionStorage eviction during external OAuth bounces). Returns true
134
+ * if at least one write succeeded.
135
+ *
136
+ * @param state - The OAuth state value to store
137
+ * @param logger - Optional logger for warning on storage failure
138
+ * @returns true if stored in at least one storage, false otherwise
139
+ */
140
+ declare function storeState(state: string, logger?: StateLogger): boolean;
141
+ /**
142
+ * Retrieve and remove the OAuth `state`.
143
+ *
144
+ * Reads from sessionStorage first, falls back to localStorage (with 5-minute TTL).
145
+ * Removes from all storages after retrieval (one-time use). Returns null if no
146
+ * state is stored, the fallback is stale (>5 min), or storage is unavailable.
147
+ *
148
+ * @param logger - Optional logger for warning on storage failure
149
+ */
150
+ declare function retrieveState(logger?: StateLogger): string | null;
151
+
152
+ declare function cleanupStateStorage(logger?: StateLogger): void;
153
+
125
154
  /**
126
155
  * Billing checkout / portal session types.
127
156
  *
@@ -716,6 +745,25 @@ interface ContractWizardSubscriptionOptions {
716
745
  organizationId?: string;
717
746
  }
718
747
 
748
+ /** OAuth token operations - exchangeCodeForTokens / refreshAccessToken / signOutToken */
749
+
750
+ /**
751
+ * Optional OAuth `state` validation for {@link exchangeCodeForTokens}.
752
+ *
753
+ * If a `state` is supplied on EITHER side — `expectedState` (the value persisted
754
+ * at `redirectToAuthorize`) or `actualState` (the value returned on the callback
755
+ * URL) — both must be present and equal before any token exchange. A mismatch
756
+ * OR an omitted counterpart fails closed (no exchange) to defend against CSRF
757
+ * (RFC 6749 §10.12 / #3841). Validation is skipped only when BOTH are omitted
758
+ * (backward compatible — callers that don't opt in are unaffected).
759
+ */
760
+ interface ExchangeCodeForTokensOptions {
761
+ /** Stored state from `redirectToAuthorize` (e.g. `retrieveState()`) */
762
+ expectedState?: string;
763
+ /** State returned on the OAuth callback URL */
764
+ actualState?: string;
765
+ }
766
+
719
767
  /** Redirect and URL generation - redirectToLogin / redirectToAuthorize / redirectToLogout / getLoginUrl / getSignupUrl / getLogoutUrl */
720
768
 
721
769
  /**
@@ -755,7 +803,7 @@ declare function createFFIDClient(config: FFIDConfig): {
755
803
  getLogoutUrl: (postLogoutRedirectUri?: string) => string;
756
804
  getSignupUrl: (redirectUrl?: string) => string;
757
805
  createError: (code: string, message: string) => FFIDError;
758
- exchangeCodeForTokens: (code: string, codeVerifier?: string) => Promise<FFIDApiResponse<void>>;
806
+ exchangeCodeForTokens: (code: string, codeVerifier?: string, opts?: ExchangeCodeForTokensOptions) => Promise<FFIDApiResponse<void>>;
759
807
  refreshAccessToken: () => Promise<FFIDApiResponse<void>>;
760
808
  checkSubscription: (params: {
761
809
  userId?: string;
@@ -857,6 +905,52 @@ declare class FFIDSDKError extends Error {
857
905
  constructor(code: string, message: string);
858
906
  }
859
907
 
908
+ /**
909
+ * OAuth redirect callback handler
910
+ *
911
+ * `handleRedirectCallback` is the convenience counterpart to
912
+ * `redirectToAuthorize`: it reads `code` + `state` from the callback URL,
913
+ * validates the OAuth `state` against the value persisted at authorize time
914
+ * (CSRF protection, RFC 6749 §10.12), retrieves the PKCE verifier, exchanges
915
+ * the code for tokens, and cleans the params out of the URL on success.
916
+ */
917
+
918
+ /**
919
+ * Minimal client surface required by {@link handleRedirectCallback}.
920
+ * A full {@link FFIDClient} satisfies this structurally.
921
+ */
922
+ type HandleRedirectCallbackClient = Pick<FFIDClient, 'exchangeCodeForTokens' | 'createError' | 'logger'>;
923
+ /** Options for {@link handleRedirectCallback} */
924
+ interface HandleRedirectCallbackOptions {
925
+ /**
926
+ * Callback URL (or query string) to read `code` / `state` from. Accepts an
927
+ * absolute URL, a relative URL, or a bare query string. Defaults to
928
+ * `window.location.search` in the browser.
929
+ */
930
+ url?: string;
931
+ }
932
+ /**
933
+ * Complete an OAuth authorization-code redirect.
934
+ *
935
+ * Behavior:
936
+ * 1. Reads `code` + `state` from `options.url ?? window.location.search`.
937
+ * 2. CSRF guard: if a `state` exists on EITHER side (a stored state from
938
+ * authorize OR a `state` on the callback URL), the two MUST match — mismatch,
939
+ * a missing stored state, or an **omitted** callback `state` all **fail closed**
940
+ * (returns an error, performs no exchange). Validation is skipped ONLY when
941
+ * neither side has any state (a genuine no-state flow). Omitting the callback
942
+ * `state` does NOT bypass the check (#3841).
943
+ * 3. Retrieves the PKCE verifier and exchanges the code for tokens.
944
+ * 4. On success, removes `code` + `state` from the browser URL.
945
+ *
946
+ * SSR-safe: when there is no `window` and no `options.url`, no exchange is
947
+ * attempted and an error result is returned.
948
+ *
949
+ * @param client - FFID client (or any object exposing exchangeCodeForTokens / createError / logger)
950
+ * @param options - Optional callback URL override
951
+ */
952
+ declare function handleRedirectCallback(client: HandleRedirectCallbackClient, options?: HandleRedirectCallbackOptions): Promise<FFIDApiResponse<void>>;
953
+
860
954
  /**
861
955
  * Redirect URI normalization (SDK copy)
862
956
  *
@@ -1565,4 +1659,4 @@ declare function createInquiryMethods(deps: InquiryMethodsDeps): {
1565
1659
  };
1566
1660
  type FFIDInquiryClient = ReturnType<typeof createInquiryMethods>;
1567
1661
 
1568
- export { ACCESS_GRANTING_EFFECTIVE_STATUSES, AnnouncementListResponse, BLOCKING_EFFECTIVE_STATUSES, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EffectiveSubscriptionStatus, type FFIDAddMemberParams, type FFIDAddMemberRequest, type FFIDAddMemberResponse, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDAssignableMemberRole, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckServiceAccessParams, type FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, type FFIDCreateCheckoutParams, type FFIDCreatePortalParams, FFIDError, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, type FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, type FFIDMemberRole, type FFIDMemberStatus, type FFIDNewsletterBodySource, type FFIDNewsletterCampaignStatus, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterDispatchParams, type FFIDNewsletterDispatchResponse, type FFIDNewsletterSegment, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOAuthUserInfoSubscription, FFIDOrganization, type FFIDOrganizationMember, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, type FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, type FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, FFIDServiceAccessDecision, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, type FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_DISPATCH_MAX_RECIPIENTS, FFID_NEWSLETTER_TYPES, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, hasAccessFromUserinfo, isBlockedFromUserinfo, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
1662
+ export { ACCESS_GRANTING_EFFECTIVE_STATUSES, AnnouncementListResponse, BLOCKING_EFFECTIVE_STATUSES, type ComputeEffectiveStatusInput, type ContractWizardFlowType, type ContractWizardResubscribeOptions, type ContractWizardSubscribeOptions, type ContractWizardSubscriptionOptions, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EffectiveSubscriptionStatus, type ExchangeCodeForTokensOptions, type FFIDAddMemberParams, type FFIDAddMemberRequest, type FFIDAddMemberResponse, FFIDAnnouncementsApiResponse, type FFIDAnnouncementsClient, FFIDAnnouncementsClientConfig, FFIDAnnouncementsLogger, FFIDApiResponse, type FFIDAssignableMemberRole, type FFIDBillingInterval, FFIDCacheAdapter, type FFIDCancelPendingDowngradeResponse, type FFIDCancelSubscriptionParams, type FFIDCancelSubscriptionResponse, type FFIDChangePlanParams, type FFIDChangePlanResponse, FFIDCheckServiceAccessParams, type FFIDCheckoutSessionResponse, type FFIDClient, FFIDConfig, type FFIDCreateCheckoutParams, type FFIDCreatePortalParams, FFIDError, type FFIDInquiryClient, FFIDInquiryCreateParams, FFIDInquiryCreateResponse, type FFIDListMembersResponse, type FFIDListPlansResponse, FFIDLogger, type FFIDMemberRole, type FFIDMemberStatus, type FFIDNewsletterBodySource, type FFIDNewsletterCampaignStatus, type FFIDNewsletterClient, type FFIDNewsletterConfirmParams, type FFIDNewsletterConfirmResponse, type FFIDNewsletterDispatchParams, type FFIDNewsletterDispatchResponse, type FFIDNewsletterSegment, type FFIDNewsletterSubscribeParams, type FFIDNewsletterSubscribeResponse, type FFIDNewsletterType, type FFIDNewsletterUnsubscribeParams, type FFIDNewsletterUnsubscribeResponse, FFIDOAuthUserInfo, FFIDOAuthUserInfoSubscription, FFIDOrganization, type FFIDOrganizationMember, type FFIDOtpSendResponse, type FFIDOtpVerifyResponse, type FFIDPasswordResetConfirmResponse, type FFIDPasswordResetResponse, type FFIDPasswordResetVerifyResponse, type FFIDPlanChangeLineItem, type FFIDPlanChangePreview, type FFIDPlanChangePreviewResponse, type FFIDPlanInfo, type FFIDPortalSessionResponse, type FFIDPreviewPlanChangeParams, type FFIDPreviewSeatChangeParams, FFIDProfileCallOptions, FFIDProvider, type FFIDProviderProps, FFIDRedirectResult, type FFIDRemoveMemberResponse, type FFIDResetSessionResponse, FFIDSDKError, type FFIDSeatChangeLineItem, type FFIDSeatChangePreview, type FFIDSeatChangePreviewResponse, FFIDServiceAccessDecision, type FFIDServiceInfo, FFIDSessionResponse, type FFIDSubscribeParams, type FFIDSubscribeResponse, FFIDSubscription, FFIDSubscriptionCheckResponse, FFIDSubscriptionContextValue, type FFIDSubscriptionDetail, FFIDSubscriptionStatus, type FFIDSubscriptionSummary, type FFIDSupportedCurrency, type FFIDUpdateMemberRoleResponse, FFIDUpdateUserProfileRequest, FFIDUser, FFIDUserProfile, FFIDVerifyAccessTokenOptions, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_NEWSLETTER_DISPATCH_MAX_RECIPIENTS, FFID_NEWSLETTER_TYPES, type HandleRedirectCallbackClient, type HandleRedirectCallbackOptions, type KVNamespaceLike, ListAnnouncementsOptions, type NormalizeRedirectUriResult, type RedirectToAuthorizeOptions, type TokenData, type TokenStore, type UseFFIDReturn, type UseRequireActiveSubscriptionOptions, type UseRequireActiveSubscriptionReturn, type WithFFIDAuthOptions, type WithSubscriptionOptions, cleanupStateStorage as clearState, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, generateCodeChallenge, generateCodeVerifier, handleRedirectCallback, hasAccessFromUserinfo, isBlockedFromUserinfo, normalizeRedirectUri, retrieveCodeVerifier, retrieveState, storeCodeVerifier, storeState, useFFID, useRequireActiveSubscription, useSubscription, withFFIDAuth, withSubscription };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { useFFIDContext, useSubscription } from './chunk-KB2JG64Z.js';
2
- export { ACCESS_GRANTING_EFFECTIVE_STATUSES, BLOCKING_EFFECTIVE_STATUSES, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EFFECTIVE_SUBSCRIPTION_STATUSES, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, hasAccessFromUserinfo, isBlockedFromUserinfo, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, storeCodeVerifier, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-KB2JG64Z.js';
1
+ import { useFFIDContext, useSubscription } from './chunk-RATTQIKM.js';
2
+ export { ACCESS_GRANTING_EFFECTIVE_STATUSES, BLOCKING_EFFECTIVE_STATUSES, DEFAULT_API_BASE_URL, DEFAULT_OAUTH_SCOPES, EFFECTIVE_SUBSCRIPTION_STATUSES, FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDProvider, FFIDSDKError, FFIDSubscriptionBadge, FFIDUserMenu, FFID_ANNOUNCEMENTS_ERROR_CODES, FFID_INQUIRY_CATEGORIES, FFID_INQUIRY_CATEGORIES_SITE_2026, cleanupStateStorage as clearState, computeEffectiveStatusFromSession, createFFIDAnnouncementsClient, createFFIDClient, createTokenStore, generateCodeChallenge, generateCodeVerifier, handleRedirectCallback, hasAccessFromUserinfo, isBlockedFromUserinfo, isFFIDInquiryCategorySite2026, normalizeRedirectUri, retrieveCodeVerifier, retrieveState, storeCodeVerifier, storeState, useFFID, useFFIDAnnouncements, useSubscription, withSubscription } from './chunk-RATTQIKM.js';
3
3
  export { ALL_DENIED_EXCEPT_NECESSARY, CONSENT_COOKIE_NAME, CONSENT_DISMISSAL_TIMESTAMP_KEY, COOKIE_VERSION, DEFAULT_CONSENT_ERROR_MESSAGES, FFIDAnalyticsProvider, FFIDConsentError, FFIDCookieBanner, FFIDCookieLink, FFIDCookieSettings, FFID_CONSENT_ERROR_CODES, clearConsentDismissalTimestamp, decodeConsentCookie, encodeConsentCookie, readConsentCookie, readConsentDismissalTimestamp, useFFIDConsent, useFFIDConsentPreferences, writeConsentCookie, writeConsentDismissalTimestamp } from './chunk-M4N2PUX6.js';
4
4
  import { useEffect, useRef } from 'react';
5
5
  import { jsx, Fragment } from 'react/jsx-runtime';
@@ -119,6 +119,9 @@ function normalizeUserinfo(raw) {
119
119
  return {
120
120
  sub: raw.sub,
121
121
  email: raw.email,
122
+ // #3791: undefined → undefined を保つ(false に丸めない)。古い FFID は wire に
123
+ // 含めないため、consumer は undefined を「未確認」ではなく「不明」として扱える。
124
+ emailVerified: raw.email_verified,
122
125
  name: raw.name,
123
126
  picture: raw.picture,
124
127
  companyName: raw.company_name ?? null,
@@ -374,6 +377,9 @@ function createVerifyAccessToken(deps) {
374
377
  const base = {
375
378
  sub: introspectResponse.sub,
376
379
  email: introspectResponse.email ?? null,
380
+ // #3791: preserve undefined (do NOT coerce to false) so introspect-strategy
381
+ // callers can distinguish "verified" / "not verified" / "older server".
382
+ email_verified: introspectResponse.email_verified,
377
383
  name: introspectResponse.name ?? null,
378
384
  picture: introspectResponse.picture ?? null,
379
385
  company_name: introspectResponse.company_name ?? null,
@@ -929,7 +935,7 @@ function createProfileMethods(deps) {
929
935
  }
930
936
 
931
937
  // src/client/version-check.ts
932
- var SDK_VERSION = "5.12.0";
938
+ var SDK_VERSION = "5.13.0";
933
939
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
934
940
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
935
941
  function sdkHeaders() {
@@ -1001,9 +1007,20 @@ function createOAuthTokenMethods(deps) {
1001
1007
  logger,
1002
1008
  errorCodes
1003
1009
  } = deps;
1004
- async function exchangeCodeForTokens(code, codeVerifier) {
1010
+ async function exchangeCodeForTokens(code, codeVerifier, opts) {
1005
1011
  const url = `${baseUrl}${OAUTH_TOKEN_ENDPOINT}`;
1006
1012
  logger.debug("Exchanging code for tokens:", url);
1013
+ if (opts?.expectedState !== void 0 || opts?.actualState !== void 0) {
1014
+ if (opts?.expectedState !== opts?.actualState) {
1015
+ logger.error("Token exchange aborted: OAuth state mismatch or omitted (possible CSRF)");
1016
+ return {
1017
+ error: {
1018
+ code: errorCodes.STATE_MISMATCH_ERROR,
1019
+ message: "OAuth state \u304C\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002CSRF \u306E\u53EF\u80FD\u6027\u304C\u3042\u308B\u305F\u3081\u8A8D\u8A3C\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F"
1020
+ }
1021
+ };
1022
+ }
1023
+ }
1007
1024
  const effectiveRedirectUri = resolvedRedirectUri ?? (typeof window !== "undefined" ? window.location.origin + window.location.pathname : null);
1008
1025
  if (!effectiveRedirectUri) {
1009
1026
  logger.error("redirectUri is required for token exchange in SSR environments. Set config.redirectUri explicitly.");
@@ -1448,6 +1465,46 @@ function base64UrlEncode(buffer) {
1448
1465
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1449
1466
  }
1450
1467
 
1468
+ // src/auth/state.ts
1469
+ var STATE_STORAGE_KEY = "ffid_oauth_state";
1470
+ var STATE_FALLBACK_STORAGE_KEY = "ffid_oauth_state_fb";
1471
+ var STATE_FALLBACK_TIMESTAMP_KEY = "ffid_oauth_state_fb_ts";
1472
+ function storeState(state, logger) {
1473
+ if (typeof window === "undefined") {
1474
+ logger?.warn("storeState: storage is not available in SSR context");
1475
+ return false;
1476
+ }
1477
+ let sessionStored = false;
1478
+ try {
1479
+ window.sessionStorage.setItem(STATE_STORAGE_KEY, state);
1480
+ sessionStored = true;
1481
+ } catch (error) {
1482
+ logger?.warn("storeState: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1483
+ }
1484
+ let localStored = false;
1485
+ try {
1486
+ window.localStorage.setItem(STATE_FALLBACK_STORAGE_KEY, state);
1487
+ window.localStorage.setItem(STATE_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
1488
+ localStored = true;
1489
+ } catch (error) {
1490
+ logger?.warn("storeState: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1491
+ }
1492
+ return sessionStored || localStored;
1493
+ }
1494
+ function cleanupStateStorage(logger) {
1495
+ try {
1496
+ window.sessionStorage.removeItem(STATE_STORAGE_KEY);
1497
+ } catch (error) {
1498
+ logger?.warn("retrieveState: sessionStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1499
+ }
1500
+ try {
1501
+ window.localStorage.removeItem(STATE_FALLBACK_STORAGE_KEY);
1502
+ window.localStorage.removeItem(STATE_FALLBACK_TIMESTAMP_KEY);
1503
+ } catch (error) {
1504
+ logger?.warn("retrieveState: localStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1505
+ }
1506
+ }
1507
+
1451
1508
  // src/client/redirect.ts
1452
1509
  var OAUTH_AUTHORIZE_ENDPOINT = "/api/v1/oauth/authorize";
1453
1510
  var AUTH_LOGOUT_ENDPOINT = "/api/v1/auth/logout";
@@ -1579,6 +1636,7 @@ function createRedirectMethods(deps) {
1579
1636
  const recentCount = getRecentRedirectCount(authorizeKey, now, logger);
1580
1637
  if (recentCount >= REDIRECT_LOOP_THRESHOLD) {
1581
1638
  cleanupVerifierStorage(logger);
1639
+ cleanupStateStorage(logger);
1582
1640
  logger.warn("[FFID SDK] redirect loop detected \u2014 \u81EA\u52D5\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3092\u505C\u6B62\u3057\u307E\u3057\u305F", {
1583
1641
  authorizeKey,
1584
1642
  recentCount,
@@ -1602,6 +1660,11 @@ function createRedirectMethods(deps) {
1602
1660
  return { success: false, error: errorMessage };
1603
1661
  }
1604
1662
  const state = generateRandomState();
1663
+ if (!storeState(state, logger)) {
1664
+ logger.error(
1665
+ "redirectToAuthorize: OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\u30B3\u30FC\u30EB\u30D0\u30C3\u30AF\u3067\u306E CSRF \u691C\u8A3C\u304C\u5931\u6557\u3057\u307E\u3059"
1666
+ );
1667
+ }
1605
1668
  const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
1606
1669
  const params = new URLSearchParams({
1607
1670
  response_type: "code",
@@ -2316,7 +2379,8 @@ var FFID_ERROR_CODES = {
2316
2379
  TOKEN_EXCHANGE_ERROR: "TOKEN_EXCHANGE_ERROR",
2317
2380
  TOKEN_REFRESH_ERROR: "TOKEN_REFRESH_ERROR",
2318
2381
  NO_TOKENS: "NO_TOKENS",
2319
- TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
2382
+ TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR",
2383
+ STATE_MISMATCH_ERROR: "STATE_MISMATCH_ERROR"
2320
2384
  };
2321
2385
  var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
2322
2386
  var DEFAULT_ALLOW_GRACE = true;
@@ -1,5 +1,5 @@
1
- import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-Dx4oc4Cw.cjs';
2
- export { f as FFIDAddMemberParams, g as FFIDAddMemberRequest, h as FFIDAddMemberResponse, i as FFIDAssignableMemberRole, j as FFIDCacheConfig, k as FFIDClient, l as FFIDConfig, m as FFIDListMembersResponse, n as FFIDMemberRole, o as FFIDOrganization, p as FFIDOrganizationMember, q as FFIDOtpSendResponse, r as FFIDOtpVerifyResponse, s as FFIDPasswordResetConfirmResponse, t as FFIDPasswordResetResponse, u as FFIDPasswordResetVerifyResponse, v as FFIDProfileCallOptions, w as FFIDRemoveMemberResponse, x as FFIDResetSessionResponse, y as FFIDSubscription, z as FFIDUpdateMemberRoleResponse, A as FFIDUpdateUserProfileRequest, B as FFIDUser, C as FFIDUserProfile, T as TokenData, D as TokenStore, E as createFFIDClient, G as createTokenStore } from '../ffid-client-Dx4oc4Cw.cjs';
1
+ import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-C3K3sAqq.cjs';
2
+ export { f as FFIDAddMemberParams, g as FFIDAddMemberRequest, h as FFIDAddMemberResponse, i as FFIDAssignableMemberRole, j as FFIDCacheConfig, k as FFIDClient, l as FFIDConfig, m as FFIDListMembersResponse, n as FFIDMemberRole, o as FFIDOrganization, p as FFIDOrganizationMember, q as FFIDOtpSendResponse, r as FFIDOtpVerifyResponse, s as FFIDPasswordResetConfirmResponse, t as FFIDPasswordResetResponse, u as FFIDPasswordResetVerifyResponse, v as FFIDProfileCallOptions, w as FFIDRemoveMemberResponse, x as FFIDResetSessionResponse, y as FFIDSubscription, z as FFIDUpdateMemberRoleResponse, A as FFIDUpdateUserProfileRequest, B as FFIDUser, C as FFIDUserProfile, T as TokenData, D as TokenStore, E as createFFIDClient, G as createTokenStore } from '../ffid-client-C3K3sAqq.cjs';
3
3
  export { D as DEFAULT_API_BASE_URL, a as DEFAULT_OAUTH_SCOPES } from '../constants-D61jqRIO.cjs';
4
4
  import { z } from 'zod';
5
5
  import '../types-BeVl-z12.cjs';
@@ -1,5 +1,5 @@
1
- import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-5IprSUVR.js';
2
- export { f as FFIDAddMemberParams, g as FFIDAddMemberRequest, h as FFIDAddMemberResponse, i as FFIDAssignableMemberRole, j as FFIDCacheConfig, k as FFIDClient, l as FFIDConfig, m as FFIDListMembersResponse, n as FFIDMemberRole, o as FFIDOrganization, p as FFIDOrganizationMember, q as FFIDOtpSendResponse, r as FFIDOtpVerifyResponse, s as FFIDPasswordResetConfirmResponse, t as FFIDPasswordResetResponse, u as FFIDPasswordResetVerifyResponse, v as FFIDProfileCallOptions, w as FFIDRemoveMemberResponse, x as FFIDResetSessionResponse, y as FFIDSubscription, z as FFIDUpdateMemberRoleResponse, A as FFIDUpdateUserProfileRequest, B as FFIDUser, C as FFIDUserProfile, T as TokenData, D as TokenStore, E as createFFIDClient, G as createTokenStore } from '../ffid-client-5IprSUVR.js';
1
+ import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-BG0Qr86U.js';
2
+ export { f as FFIDAddMemberParams, g as FFIDAddMemberRequest, h as FFIDAddMemberResponse, i as FFIDAssignableMemberRole, j as FFIDCacheConfig, k as FFIDClient, l as FFIDConfig, m as FFIDListMembersResponse, n as FFIDMemberRole, o as FFIDOrganization, p as FFIDOrganizationMember, q as FFIDOtpSendResponse, r as FFIDOtpVerifyResponse, s as FFIDPasswordResetConfirmResponse, t as FFIDPasswordResetResponse, u as FFIDPasswordResetVerifyResponse, v as FFIDProfileCallOptions, w as FFIDRemoveMemberResponse, x as FFIDResetSessionResponse, y as FFIDSubscription, z as FFIDUpdateMemberRoleResponse, A as FFIDUpdateUserProfileRequest, B as FFIDUser, C as FFIDUserProfile, T as TokenData, D as TokenStore, E as createFFIDClient, G as createTokenStore } from '../ffid-client-BG0Qr86U.js';
3
3
  export { D as DEFAULT_API_BASE_URL, a as DEFAULT_OAUTH_SCOPES } from '../constants-D61jqRIO.js';
4
4
  import { z } from 'zod';
5
5
  import '../types-BeVl-z12.js';
@@ -118,6 +118,9 @@ function normalizeUserinfo(raw) {
118
118
  return {
119
119
  sub: raw.sub,
120
120
  email: raw.email,
121
+ // #3791: undefined → undefined を保つ(false に丸めない)。古い FFID は wire に
122
+ // 含めないため、consumer は undefined を「未確認」ではなく「不明」として扱える。
123
+ emailVerified: raw.email_verified,
121
124
  name: raw.name,
122
125
  picture: raw.picture,
123
126
  companyName: raw.company_name ?? null,
@@ -373,6 +376,9 @@ function createVerifyAccessToken(deps) {
373
376
  const base = {
374
377
  sub: introspectResponse.sub,
375
378
  email: introspectResponse.email ?? null,
379
+ // #3791: preserve undefined (do NOT coerce to false) so introspect-strategy
380
+ // callers can distinguish "verified" / "not verified" / "older server".
381
+ email_verified: introspectResponse.email_verified,
376
382
  name: introspectResponse.name ?? null,
377
383
  picture: introspectResponse.picture ?? null,
378
384
  company_name: introspectResponse.company_name ?? null,
@@ -928,7 +934,7 @@ function createProfileMethods(deps) {
928
934
  }
929
935
 
930
936
  // src/client/version-check.ts
931
- var SDK_VERSION = "5.12.0";
937
+ var SDK_VERSION = "5.13.0";
932
938
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
933
939
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
934
940
  function sdkHeaders() {
@@ -1000,9 +1006,20 @@ function createOAuthTokenMethods(deps) {
1000
1006
  logger,
1001
1007
  errorCodes
1002
1008
  } = deps;
1003
- async function exchangeCodeForTokens(code, codeVerifier) {
1009
+ async function exchangeCodeForTokens(code, codeVerifier, opts) {
1004
1010
  const url = `${baseUrl}${OAUTH_TOKEN_ENDPOINT}`;
1005
1011
  logger.debug("Exchanging code for tokens:", url);
1012
+ if (opts?.expectedState !== void 0 || opts?.actualState !== void 0) {
1013
+ if (opts?.expectedState !== opts?.actualState) {
1014
+ logger.error("Token exchange aborted: OAuth state mismatch or omitted (possible CSRF)");
1015
+ return {
1016
+ error: {
1017
+ code: errorCodes.STATE_MISMATCH_ERROR,
1018
+ message: "OAuth state \u304C\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002CSRF \u306E\u53EF\u80FD\u6027\u304C\u3042\u308B\u305F\u3081\u8A8D\u8A3C\u3092\u4E2D\u6B62\u3057\u307E\u3057\u305F"
1019
+ }
1020
+ };
1021
+ }
1022
+ }
1006
1023
  const effectiveRedirectUri = resolvedRedirectUri ?? (typeof window !== "undefined" ? window.location.origin + window.location.pathname : null);
1007
1024
  if (!effectiveRedirectUri) {
1008
1025
  logger.error("redirectUri is required for token exchange in SSR environments. Set config.redirectUri explicitly.");
@@ -1447,6 +1464,46 @@ function base64UrlEncode(buffer) {
1447
1464
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1448
1465
  }
1449
1466
 
1467
+ // src/auth/state.ts
1468
+ var STATE_STORAGE_KEY = "ffid_oauth_state";
1469
+ var STATE_FALLBACK_STORAGE_KEY = "ffid_oauth_state_fb";
1470
+ var STATE_FALLBACK_TIMESTAMP_KEY = "ffid_oauth_state_fb_ts";
1471
+ function storeState(state, logger) {
1472
+ if (typeof window === "undefined") {
1473
+ logger?.warn("storeState: storage is not available in SSR context");
1474
+ return false;
1475
+ }
1476
+ let sessionStored = false;
1477
+ try {
1478
+ window.sessionStorage.setItem(STATE_STORAGE_KEY, state);
1479
+ sessionStored = true;
1480
+ } catch (error) {
1481
+ logger?.warn("storeState: sessionStorage \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1482
+ }
1483
+ let localStored = false;
1484
+ try {
1485
+ window.localStorage.setItem(STATE_FALLBACK_STORAGE_KEY, state);
1486
+ window.localStorage.setItem(STATE_FALLBACK_TIMESTAMP_KEY, String(Date.now()));
1487
+ localStored = true;
1488
+ } catch (error) {
1489
+ logger?.warn("storeState: localStorage fallback \u3078\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1490
+ }
1491
+ return sessionStored || localStored;
1492
+ }
1493
+ function cleanupStateStorage(logger) {
1494
+ try {
1495
+ window.sessionStorage.removeItem(STATE_STORAGE_KEY);
1496
+ } catch (error) {
1497
+ logger?.warn("retrieveState: sessionStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1498
+ }
1499
+ try {
1500
+ window.localStorage.removeItem(STATE_FALLBACK_STORAGE_KEY);
1501
+ window.localStorage.removeItem(STATE_FALLBACK_TIMESTAMP_KEY);
1502
+ } catch (error) {
1503
+ logger?.warn("retrieveState: localStorage \u306E\u30AF\u30EA\u30FC\u30F3\u30A2\u30C3\u30D7\u306B\u5931\u6557\u3057\u307E\u3057\u305F:", error);
1504
+ }
1505
+ }
1506
+
1450
1507
  // src/client/redirect.ts
1451
1508
  var OAUTH_AUTHORIZE_ENDPOINT = "/api/v1/oauth/authorize";
1452
1509
  var AUTH_LOGOUT_ENDPOINT = "/api/v1/auth/logout";
@@ -1578,6 +1635,7 @@ function createRedirectMethods(deps) {
1578
1635
  const recentCount = getRecentRedirectCount(authorizeKey, now, logger);
1579
1636
  if (recentCount >= REDIRECT_LOOP_THRESHOLD) {
1580
1637
  cleanupVerifierStorage(logger);
1638
+ cleanupStateStorage(logger);
1581
1639
  logger.warn("[FFID SDK] redirect loop detected \u2014 \u81EA\u52D5\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3092\u505C\u6B62\u3057\u307E\u3057\u305F", {
1582
1640
  authorizeKey,
1583
1641
  recentCount,
@@ -1601,6 +1659,11 @@ function createRedirectMethods(deps) {
1601
1659
  return { success: false, error: errorMessage };
1602
1660
  }
1603
1661
  const state = generateRandomState();
1662
+ if (!storeState(state, logger)) {
1663
+ logger.error(
1664
+ "redirectToAuthorize: OAuth state \u3092\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF08storage \u5229\u7528\u4E0D\u53EF\uFF09\u3002\u30B3\u30FC\u30EB\u30D0\u30C3\u30AF\u3067\u306E CSRF \u691C\u8A3C\u304C\u5931\u6557\u3057\u307E\u3059"
1665
+ );
1666
+ }
1604
1667
  const redirectUri = resolvedRedirectUri ?? window.location.origin + window.location.pathname;
1605
1668
  const params = new URLSearchParams({
1606
1669
  response_type: "code",
@@ -2315,7 +2378,8 @@ var FFID_ERROR_CODES = {
2315
2378
  TOKEN_EXCHANGE_ERROR: "TOKEN_EXCHANGE_ERROR",
2316
2379
  TOKEN_REFRESH_ERROR: "TOKEN_REFRESH_ERROR",
2317
2380
  NO_TOKENS: "NO_TOKENS",
2318
- TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
2381
+ TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR",
2382
+ STATE_MISMATCH_ERROR: "STATE_MISMATCH_ERROR"
2319
2383
  };
2320
2384
  var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
2321
2385
  var DEFAULT_ALLOW_GRACE = true;
@@ -1,4 +1,4 @@
1
- import { k as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-Dx4oc4Cw.cjs';
1
+ import { k as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-C3K3sAqq.cjs';
2
2
  import '../../types-BeVl-z12.cjs';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { k as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-5IprSUVR.js';
1
+ import { k as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-BG0Qr86U.js';
2
2
  import '../../types-BeVl-z12.js';
3
3
 
4
4
  /**