@feelflow/ffid-sdk 5.19.0 → 5.22.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.
Files changed (34) hide show
  1. package/README.md +1 -0
  2. package/dist/agency/index.cjs +4 -2
  3. package/dist/agency/index.js +4 -2
  4. package/dist/announcements/index.cjs +2 -1
  5. package/dist/announcements/index.js +2 -1
  6. package/dist/{chunk-D3PZ6SZB.js → chunk-7NRO2TBG.js} +108 -53
  7. package/dist/{chunk-TW2FXASO.cjs → chunk-EM5EGNGE.cjs} +108 -53
  8. package/dist/components/index.cjs +8 -8
  9. package/dist/components/index.d.cts +1 -1
  10. package/dist/components/index.d.ts +1 -1
  11. package/dist/components/index.js +1 -1
  12. package/dist/{ffid-client-BuDM5tmq.d.cts → ffid-client-CEJMpqRZ.d.cts} +55 -9
  13. package/dist/{ffid-client-D0x8TBS5.d.ts → ffid-client-DM0ZhIDV.d.ts} +55 -9
  14. package/dist/{index-Bkul-fRw.d.cts → index-btouGGKr.d.cts} +56 -9
  15. package/dist/{index-Bkul-fRw.d.ts → index-btouGGKr.d.ts} +56 -9
  16. package/dist/index.cjs +42 -42
  17. package/dist/index.d.cts +44 -8
  18. package/dist/index.d.ts +44 -8
  19. package/dist/index.js +2 -2
  20. package/dist/legal/index.cjs +2 -1
  21. package/dist/legal/index.js +2 -1
  22. package/dist/server/index.cjs +94 -48
  23. package/dist/server/index.d.cts +3 -3
  24. package/dist/server/index.d.ts +3 -3
  25. package/dist/server/index.js +94 -48
  26. package/dist/server/test/index.d.cts +2 -2
  27. package/dist/server/test/index.d.ts +2 -2
  28. package/dist/{types-BeVl-z12.d.cts → types-Cjb9J0rL.d.cts} +2 -1
  29. package/dist/{types-BeVl-z12.d.ts → types-Cjb9J0rL.d.ts} +2 -1
  30. package/dist/webhooks/index.cjs +2 -2
  31. package/dist/webhooks/index.d.cts +1 -1
  32. package/dist/webhooks/index.d.ts +1 -1
  33. package/dist/webhooks/index.js +2 -2
  34. package/package.json +1 -1
@@ -1,34 +1,34 @@
1
1
  'use strict';
2
2
 
3
- var chunkTW2FXASO_cjs = require('../chunk-TW2FXASO.cjs');
3
+ var chunkEM5EGNGE_cjs = require('../chunk-EM5EGNGE.cjs');
4
4
 
5
5
 
6
6
 
7
7
  Object.defineProperty(exports, "FFIDAnnouncementBadge", {
8
8
  enumerable: true,
9
- get: function () { return chunkTW2FXASO_cjs.FFIDAnnouncementBadge; }
9
+ get: function () { return chunkEM5EGNGE_cjs.FFIDAnnouncementBadge; }
10
10
  });
11
11
  Object.defineProperty(exports, "FFIDAnnouncementList", {
12
12
  enumerable: true,
13
- get: function () { return chunkTW2FXASO_cjs.FFIDAnnouncementList; }
13
+ get: function () { return chunkEM5EGNGE_cjs.FFIDAnnouncementList; }
14
14
  });
15
15
  Object.defineProperty(exports, "FFIDInquiryForm", {
16
16
  enumerable: true,
17
- get: function () { return chunkTW2FXASO_cjs.FFIDInquiryForm; }
17
+ get: function () { return chunkEM5EGNGE_cjs.FFIDInquiryForm; }
18
18
  });
19
19
  Object.defineProperty(exports, "FFIDLoginButton", {
20
20
  enumerable: true,
21
- get: function () { return chunkTW2FXASO_cjs.FFIDLoginButton; }
21
+ get: function () { return chunkEM5EGNGE_cjs.FFIDLoginButton; }
22
22
  });
23
23
  Object.defineProperty(exports, "FFIDOrganizationSwitcher", {
24
24
  enumerable: true,
25
- get: function () { return chunkTW2FXASO_cjs.FFIDOrganizationSwitcher; }
25
+ get: function () { return chunkEM5EGNGE_cjs.FFIDOrganizationSwitcher; }
26
26
  });
27
27
  Object.defineProperty(exports, "FFIDSubscriptionBadge", {
28
28
  enumerable: true,
29
- get: function () { return chunkTW2FXASO_cjs.FFIDSubscriptionBadge; }
29
+ get: function () { return chunkEM5EGNGE_cjs.FFIDSubscriptionBadge; }
30
30
  });
31
31
  Object.defineProperty(exports, "FFIDUserMenu", {
32
32
  enumerable: true,
33
- get: function () { return chunkTW2FXASO_cjs.FFIDUserMenu; }
33
+ get: function () { return chunkEM5EGNGE_cjs.FFIDUserMenu; }
34
34
  });
@@ -1,3 +1,3 @@
1
- export { G as FFIDAnnouncementBadge, ag as FFIDAnnouncementBadgeClassNames, ah as FFIDAnnouncementBadgeProps, H as FFIDAnnouncementList, ai as FFIDAnnouncementListClassNames, aj as FFIDAnnouncementListProps, Q as FFIDInquiryForm, R as FFIDInquiryFormCategoryItem, S as FFIDInquiryFormClassNames, T as FFIDInquiryFormLegalLayout, U as FFIDInquiryFormOrganization, V as FFIDInquiryFormPlaceholderContext, W as FFIDInquiryFormPrefill, X as FFIDInquiryFormProps, Y as FFIDInquiryFormSubmitData, Z as FFIDInquiryFormSubmitResult, $ as FFIDLoginButton, ak as FFIDLoginButtonProps, a2 as FFIDOrganizationSwitcher, al as FFIDOrganizationSwitcherClassNames, am as FFIDOrganizationSwitcherProps, a7 as FFIDSubscriptionBadge, an as FFIDSubscriptionBadgeClassNames, ao as FFIDSubscriptionBadgeProps, a9 as FFIDUserMenu, ap as FFIDUserMenuClassNames, aq as FFIDUserMenuProps } from '../index-Bkul-fRw.cjs';
1
+ export { H as FFIDAnnouncementBadge, ai as FFIDAnnouncementBadgeClassNames, aj as FFIDAnnouncementBadgeProps, I as FFIDAnnouncementList, ak as FFIDAnnouncementListClassNames, al as FFIDAnnouncementListProps, 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, a1 as FFIDLoginButton, am as FFIDLoginButtonProps, a4 as FFIDOrganizationSwitcher, an as FFIDOrganizationSwitcherClassNames, ao as FFIDOrganizationSwitcherProps, a9 as FFIDSubscriptionBadge, ap as FFIDSubscriptionBadgeClassNames, aq as FFIDSubscriptionBadgeProps, ab as FFIDUserMenu, ar as FFIDUserMenuClassNames, as as FFIDUserMenuProps } from '../index-btouGGKr.cjs';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1,3 +1,3 @@
1
- export { G as FFIDAnnouncementBadge, ag as FFIDAnnouncementBadgeClassNames, ah as FFIDAnnouncementBadgeProps, H as FFIDAnnouncementList, ai as FFIDAnnouncementListClassNames, aj as FFIDAnnouncementListProps, Q as FFIDInquiryForm, R as FFIDInquiryFormCategoryItem, S as FFIDInquiryFormClassNames, T as FFIDInquiryFormLegalLayout, U as FFIDInquiryFormOrganization, V as FFIDInquiryFormPlaceholderContext, W as FFIDInquiryFormPrefill, X as FFIDInquiryFormProps, Y as FFIDInquiryFormSubmitData, Z as FFIDInquiryFormSubmitResult, $ as FFIDLoginButton, ak as FFIDLoginButtonProps, a2 as FFIDOrganizationSwitcher, al as FFIDOrganizationSwitcherClassNames, am as FFIDOrganizationSwitcherProps, a7 as FFIDSubscriptionBadge, an as FFIDSubscriptionBadgeClassNames, ao as FFIDSubscriptionBadgeProps, a9 as FFIDUserMenu, ap as FFIDUserMenuClassNames, aq as FFIDUserMenuProps } from '../index-Bkul-fRw.js';
1
+ export { H as FFIDAnnouncementBadge, ai as FFIDAnnouncementBadgeClassNames, aj as FFIDAnnouncementBadgeProps, I as FFIDAnnouncementList, ak as FFIDAnnouncementListClassNames, al as FFIDAnnouncementListProps, 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, a1 as FFIDLoginButton, am as FFIDLoginButtonProps, a4 as FFIDOrganizationSwitcher, an as FFIDOrganizationSwitcherClassNames, ao as FFIDOrganizationSwitcherProps, a9 as FFIDSubscriptionBadge, ap as FFIDSubscriptionBadgeClassNames, aq as FFIDSubscriptionBadgeProps, ab as FFIDUserMenu, ar as FFIDUserMenuClassNames, as as FFIDUserMenuProps } from '../index-btouGGKr.js';
2
2
  import 'react/jsx-runtime';
3
3
  import 'react';
@@ -1 +1 @@
1
- export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-D3PZ6SZB.js';
1
+ export { FFIDAnnouncementBadge, FFIDAnnouncementList, FFIDInquiryForm, FFIDLoginButton, FFIDOrganizationSwitcher, FFIDSubscriptionBadge, FFIDUserMenu } from '../chunk-7NRO2TBG.js';
@@ -1,4 +1,4 @@
1
- import { E as EffectiveSubscriptionStatus } from './types-BeVl-z12.cjs';
1
+ import { E as EffectiveSubscriptionStatus } from './types-Cjb9J0rL.cjs';
2
2
 
3
3
  /**
4
4
  * Inquiry types exposed by the FFID SDK.
@@ -1649,6 +1649,19 @@ interface FFIDSessionResponse {
1649
1649
  organizations: FFIDOrganization[];
1650
1650
  subscriptions: FFIDSubscription[];
1651
1651
  }
1652
+ /**
1653
+ * Optional metadata on successful {@link FFIDApiResponse} values (#4136).
1654
+ *
1655
+ * Present only on the success branch — error responses never carry `meta`.
1656
+ */
1657
+ interface FFIDApiResponseMeta {
1658
+ /**
1659
+ * Set when introspect-strategy verification could not use the configured
1660
+ * cache (adapter read/write failure or `crypto.subtle` unavailable).
1661
+ * Visible without a custom logger; absent when cache operated normally.
1662
+ */
1663
+ verificationCacheDegraded?: true;
1664
+ }
1652
1665
  /**
1653
1666
  * API response wrapper (discriminated union for type safety)
1654
1667
  *
@@ -1658,10 +1671,33 @@ interface FFIDSessionResponse {
1658
1671
  type FFIDApiResponse<T> = {
1659
1672
  data: T;
1660
1673
  error?: undefined;
1674
+ meta?: FFIDApiResponseMeta;
1661
1675
  } | {
1662
1676
  data?: undefined;
1663
1677
  error: FFIDError;
1664
1678
  };
1679
+ /**
1680
+ * Result of `signOut()` (#4119, extended #4136).
1681
+ *
1682
+ * Local credentials (tokens / local state) are always cleared when `signOut()`
1683
+ * resolves without `error`. `revoked` additionally indicates whether the
1684
+ * server-side revocation/sign-out actually succeeded:
1685
+ *
1686
+ * - `revoked: true` — no server-side session/token remains active.
1687
+ * - `revoked: false` — server-side revocation failed (network error or non-2xx
1688
+ * response). The access token may remain valid server-side until natural
1689
+ * expiry. Non-fatal: the local sign-out still completed, but callers that
1690
+ * need guaranteed revocation (e.g. shared-device flows) should surface this.
1691
+ *
1692
+ * Token mode (#4136): `accessTokenRevoked` / `refreshTokenRevoked` report each
1693
+ * RFC 7009 revoke call. `revoked` is `true` only when every applicable token
1694
+ * was revoked successfully. Cookie mode omits the per-token fields.
1695
+ */
1696
+ interface FFIDSignOutResult {
1697
+ revoked: boolean;
1698
+ accessTokenRevoked?: boolean;
1699
+ refreshTokenRevoked?: boolean;
1700
+ }
1665
1701
 
1666
1702
  /**
1667
1703
  * Response shape from `GET /api/v1/ext/analytics/config?service=<code>`.
@@ -1695,23 +1731,33 @@ interface FFIDAnalyticsConfig {
1695
1731
  * has been fired **3 times within 60 seconds**. Caller should surface a
1696
1732
  * manual "再度ログインする" UI rather than retry automatically (#2406 / #2411).
1697
1733
  *
1698
- * SDK 2.18.0 only ships `'redirect_loop_detected'`. Other failure paths
1699
- * (SSR environment, PKCE generation failure, empty organizationId) currently
1700
- * return `error` without a `code`. New codes will be added in future minor
1701
- * versions — treat this union as forward-extensible and do NOT exhaustively
1702
- * `switch` over it without a `default` branch for consumer code that must
1703
- * stay compatible across SDK upgrades.
1734
+ * - `'state_persistence_failed'`: `redirectToAuthorize()` could not persist
1735
+ * the OAuth CSRF `state` (storage unavailable / quota). Redirect is aborted
1736
+ * fail-closed (#4136) callers should surface a manual retry UI.
1737
+ *
1738
+ * Other failure paths (SSR environment, PKCE generation failure, empty
1739
+ * organizationId) currently return `error` without a `code`. Treat this union
1740
+ * as forward-extensible and do NOT exhaustively `switch` over it without a
1741
+ * `default` branch for consumer code that must stay compatible across SDK
1742
+ * upgrades.
1704
1743
  */
1705
- type FFIDRedirectErrorCode = 'redirect_loop_detected';
1744
+ type FFIDRedirectErrorCode = 'redirect_loop_detected' | 'state_persistence_failed';
1706
1745
  /**
1707
1746
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
1708
1747
  *
1709
1748
  * Structured return type so callers can inspect failure reasons
1710
1749
  * instead of receiving a bare `false`. When `code` is set, branch on it
1711
1750
  * for programmatic handling; otherwise log `error` for humans.
1751
+ *
1752
+ * `loopDetectionDisabled` (#4119): set to `true` when sessionStorage is
1753
+ * unavailable (iOS WebKit private mode / eviction) so redirect-loop detection
1754
+ * ran **fail-open** — the redirect fired, but repeated-redirect protection is
1755
+ * disabled for this browser session. Callers that need loop protection on
1756
+ * such browsers should add their own max-retry guard.
1712
1757
  */
1713
1758
  type FFIDRedirectResult = {
1714
1759
  success: true;
1760
+ loopDetectionDisabled?: boolean;
1715
1761
  } | {
1716
1762
  success: false;
1717
1763
  error: string;
@@ -1906,7 +1952,7 @@ interface RedirectToAuthorizeOptions {
1906
1952
  /** Creates an FFID API client instance */
1907
1953
  declare function createFFIDClient(config: FFIDConfig): {
1908
1954
  getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
1909
- signOut: () => Promise<FFIDApiResponse<void>>;
1955
+ signOut: () => Promise<FFIDApiResponse<FFIDSignOutResult>>;
1910
1956
  redirectToLogin: (options?: RedirectToAuthorizeOptions) => Promise<FFIDRedirectResult>;
1911
1957
  redirectToAuthorize: (options?: RedirectToAuthorizeOptions) => Promise<FFIDRedirectResult>;
1912
1958
  redirectToLogout: (postLogoutRedirectUri?: string) => FFIDRedirectResult;
@@ -1,4 +1,4 @@
1
- import { E as EffectiveSubscriptionStatus } from './types-BeVl-z12.js';
1
+ import { E as EffectiveSubscriptionStatus } from './types-Cjb9J0rL.js';
2
2
 
3
3
  /**
4
4
  * Inquiry types exposed by the FFID SDK.
@@ -1649,6 +1649,19 @@ interface FFIDSessionResponse {
1649
1649
  organizations: FFIDOrganization[];
1650
1650
  subscriptions: FFIDSubscription[];
1651
1651
  }
1652
+ /**
1653
+ * Optional metadata on successful {@link FFIDApiResponse} values (#4136).
1654
+ *
1655
+ * Present only on the success branch — error responses never carry `meta`.
1656
+ */
1657
+ interface FFIDApiResponseMeta {
1658
+ /**
1659
+ * Set when introspect-strategy verification could not use the configured
1660
+ * cache (adapter read/write failure or `crypto.subtle` unavailable).
1661
+ * Visible without a custom logger; absent when cache operated normally.
1662
+ */
1663
+ verificationCacheDegraded?: true;
1664
+ }
1652
1665
  /**
1653
1666
  * API response wrapper (discriminated union for type safety)
1654
1667
  *
@@ -1658,10 +1671,33 @@ interface FFIDSessionResponse {
1658
1671
  type FFIDApiResponse<T> = {
1659
1672
  data: T;
1660
1673
  error?: undefined;
1674
+ meta?: FFIDApiResponseMeta;
1661
1675
  } | {
1662
1676
  data?: undefined;
1663
1677
  error: FFIDError;
1664
1678
  };
1679
+ /**
1680
+ * Result of `signOut()` (#4119, extended #4136).
1681
+ *
1682
+ * Local credentials (tokens / local state) are always cleared when `signOut()`
1683
+ * resolves without `error`. `revoked` additionally indicates whether the
1684
+ * server-side revocation/sign-out actually succeeded:
1685
+ *
1686
+ * - `revoked: true` — no server-side session/token remains active.
1687
+ * - `revoked: false` — server-side revocation failed (network error or non-2xx
1688
+ * response). The access token may remain valid server-side until natural
1689
+ * expiry. Non-fatal: the local sign-out still completed, but callers that
1690
+ * need guaranteed revocation (e.g. shared-device flows) should surface this.
1691
+ *
1692
+ * Token mode (#4136): `accessTokenRevoked` / `refreshTokenRevoked` report each
1693
+ * RFC 7009 revoke call. `revoked` is `true` only when every applicable token
1694
+ * was revoked successfully. Cookie mode omits the per-token fields.
1695
+ */
1696
+ interface FFIDSignOutResult {
1697
+ revoked: boolean;
1698
+ accessTokenRevoked?: boolean;
1699
+ refreshTokenRevoked?: boolean;
1700
+ }
1665
1701
 
1666
1702
  /**
1667
1703
  * Response shape from `GET /api/v1/ext/analytics/config?service=<code>`.
@@ -1695,23 +1731,33 @@ interface FFIDAnalyticsConfig {
1695
1731
  * has been fired **3 times within 60 seconds**. Caller should surface a
1696
1732
  * manual "再度ログインする" UI rather than retry automatically (#2406 / #2411).
1697
1733
  *
1698
- * SDK 2.18.0 only ships `'redirect_loop_detected'`. Other failure paths
1699
- * (SSR environment, PKCE generation failure, empty organizationId) currently
1700
- * return `error` without a `code`. New codes will be added in future minor
1701
- * versions — treat this union as forward-extensible and do NOT exhaustively
1702
- * `switch` over it without a `default` branch for consumer code that must
1703
- * stay compatible across SDK upgrades.
1734
+ * - `'state_persistence_failed'`: `redirectToAuthorize()` could not persist
1735
+ * the OAuth CSRF `state` (storage unavailable / quota). Redirect is aborted
1736
+ * fail-closed (#4136) callers should surface a manual retry UI.
1737
+ *
1738
+ * Other failure paths (SSR environment, PKCE generation failure, empty
1739
+ * organizationId) currently return `error` without a `code`. Treat this union
1740
+ * as forward-extensible and do NOT exhaustively `switch` over it without a
1741
+ * `default` branch for consumer code that must stay compatible across SDK
1742
+ * upgrades.
1704
1743
  */
1705
- type FFIDRedirectErrorCode = 'redirect_loop_detected';
1744
+ type FFIDRedirectErrorCode = 'redirect_loop_detected' | 'state_persistence_failed';
1706
1745
  /**
1707
1746
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
1708
1747
  *
1709
1748
  * Structured return type so callers can inspect failure reasons
1710
1749
  * instead of receiving a bare `false`. When `code` is set, branch on it
1711
1750
  * for programmatic handling; otherwise log `error` for humans.
1751
+ *
1752
+ * `loopDetectionDisabled` (#4119): set to `true` when sessionStorage is
1753
+ * unavailable (iOS WebKit private mode / eviction) so redirect-loop detection
1754
+ * ran **fail-open** — the redirect fired, but repeated-redirect protection is
1755
+ * disabled for this browser session. Callers that need loop protection on
1756
+ * such browsers should add their own max-retry guard.
1712
1757
  */
1713
1758
  type FFIDRedirectResult = {
1714
1759
  success: true;
1760
+ loopDetectionDisabled?: boolean;
1715
1761
  } | {
1716
1762
  success: false;
1717
1763
  error: string;
@@ -1906,7 +1952,7 @@ interface RedirectToAuthorizeOptions {
1906
1952
  /** Creates an FFID API client instance */
1907
1953
  declare function createFFIDClient(config: FFIDConfig): {
1908
1954
  getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
1909
- signOut: () => Promise<FFIDApiResponse<void>>;
1955
+ signOut: () => Promise<FFIDApiResponse<FFIDSignOutResult>>;
1910
1956
  redirectToLogin: (options?: RedirectToAuthorizeOptions) => Promise<FFIDRedirectResult>;
1911
1957
  redirectToAuthorize: (options?: RedirectToAuthorizeOptions) => Promise<FFIDRedirectResult>;
1912
1958
  redirectToLogout: (postLogoutRedirectUri?: string) => FFIDRedirectResult;
@@ -80,7 +80,8 @@ declare const EFFECTIVE_SUBSCRIPTION_STATUSES: readonly ["active", "active_cance
80
80
  * `src/lib/common/subscription-helpers.ts`, and a server-side unit test pins
81
81
  * element-equality between the two arrays (#3474) — convention-only sync
82
82
  * could drift silently in the server-extending direction (a new server
83
- * literal would fall through SDK consumers' `switch` defaults).
83
+ * literal would fall through SDK consumers' `switch` defaults). The PR gate also
84
+ * runs `npm run sdk:verify-sync` for SDK/server subscription changes.
84
85
  */
85
86
  type EffectiveSubscriptionStatus = (typeof EFFECTIVE_SUBSCRIPTION_STATUSES)[number];
86
87
 
@@ -658,6 +659,19 @@ interface FFIDSessionResponse {
658
659
  organizations: FFIDOrganization[];
659
660
  subscriptions: FFIDSubscription[];
660
661
  }
662
+ /**
663
+ * Optional metadata on successful {@link FFIDApiResponse} values (#4136).
664
+ *
665
+ * Present only on the success branch — error responses never carry `meta`.
666
+ */
667
+ interface FFIDApiResponseMeta {
668
+ /**
669
+ * Set when introspect-strategy verification could not use the configured
670
+ * cache (adapter read/write failure or `crypto.subtle` unavailable).
671
+ * Visible without a custom logger; absent when cache operated normally.
672
+ */
673
+ verificationCacheDegraded?: true;
674
+ }
661
675
  /**
662
676
  * API response wrapper (discriminated union for type safety)
663
677
  *
@@ -667,10 +681,33 @@ interface FFIDSessionResponse {
667
681
  type FFIDApiResponse<T> = {
668
682
  data: T;
669
683
  error?: undefined;
684
+ meta?: FFIDApiResponseMeta;
670
685
  } | {
671
686
  data?: undefined;
672
687
  error: FFIDError;
673
688
  };
689
+ /**
690
+ * Result of `signOut()` (#4119, extended #4136).
691
+ *
692
+ * Local credentials (tokens / local state) are always cleared when `signOut()`
693
+ * resolves without `error`. `revoked` additionally indicates whether the
694
+ * server-side revocation/sign-out actually succeeded:
695
+ *
696
+ * - `revoked: true` — no server-side session/token remains active.
697
+ * - `revoked: false` — server-side revocation failed (network error or non-2xx
698
+ * response). The access token may remain valid server-side until natural
699
+ * expiry. Non-fatal: the local sign-out still completed, but callers that
700
+ * need guaranteed revocation (e.g. shared-device flows) should surface this.
701
+ *
702
+ * Token mode (#4136): `accessTokenRevoked` / `refreshTokenRevoked` report each
703
+ * RFC 7009 revoke call. `revoked` is `true` only when every applicable token
704
+ * was revoked successfully. Cookie mode omits the per-token fields.
705
+ */
706
+ interface FFIDSignOutResult {
707
+ revoked: boolean;
708
+ accessTokenRevoked?: boolean;
709
+ refreshTokenRevoked?: boolean;
710
+ }
674
711
 
675
712
  /**
676
713
  * Response shape from `GET /api/v1/ext/analytics/config?service=<code>`.
@@ -704,23 +741,33 @@ interface FFIDAnalyticsConfig {
704
741
  * has been fired **3 times within 60 seconds**. Caller should surface a
705
742
  * manual "再度ログインする" UI rather than retry automatically (#2406 / #2411).
706
743
  *
707
- * SDK 2.18.0 only ships `'redirect_loop_detected'`. Other failure paths
708
- * (SSR environment, PKCE generation failure, empty organizationId) currently
709
- * return `error` without a `code`. New codes will be added in future minor
710
- * versions — treat this union as forward-extensible and do NOT exhaustively
711
- * `switch` over it without a `default` branch for consumer code that must
712
- * stay compatible across SDK upgrades.
744
+ * - `'state_persistence_failed'`: `redirectToAuthorize()` could not persist
745
+ * the OAuth CSRF `state` (storage unavailable / quota). Redirect is aborted
746
+ * fail-closed (#4136) callers should surface a manual retry UI.
747
+ *
748
+ * Other failure paths (SSR environment, PKCE generation failure, empty
749
+ * organizationId) currently return `error` without a `code`. Treat this union
750
+ * as forward-extensible and do NOT exhaustively `switch` over it without a
751
+ * `default` branch for consumer code that must stay compatible across SDK
752
+ * upgrades.
713
753
  */
714
- type FFIDRedirectErrorCode = 'redirect_loop_detected';
754
+ type FFIDRedirectErrorCode = 'redirect_loop_detected' | 'state_persistence_failed';
715
755
  /**
716
756
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
717
757
  *
718
758
  * Structured return type so callers can inspect failure reasons
719
759
  * instead of receiving a bare `false`. When `code` is set, branch on it
720
760
  * for programmatic handling; otherwise log `error` for humans.
761
+ *
762
+ * `loopDetectionDisabled` (#4119): set to `true` when sessionStorage is
763
+ * unavailable (iOS WebKit private mode / eviction) so redirect-loop detection
764
+ * ran **fail-open** — the redirect fired, but repeated-redirect protection is
765
+ * disabled for this browser session. Callers that need loop protection on
766
+ * such browsers should add their own max-retry guard.
721
767
  */
722
768
  type FFIDRedirectResult = {
723
769
  success: true;
770
+ loopDetectionDisabled?: boolean;
724
771
  } | {
725
772
  success: false;
726
773
  error: string;
@@ -1476,4 +1523,4 @@ interface FFIDInquiryFormPlaceholderContext {
1476
1523
  }
1477
1524
  declare function FFIDInquiryForm({ mode, prefill, organizations, preselectedOrganizationId, categories, termsVersion, privacyVersion, termsHref, privacyHref, turnstileToken, turnstileSlot, onSubmit, onChange, legalLayout, messagePlaceholder, requireCategorySelection, unstyled, classNames, locale, className, }: FFIDInquiryFormProps): react_jsx_runtime.JSX.Element;
1478
1525
 
1479
- export { FFIDLoginButton as $, type AnnouncementListResponse as A, type AnnouncementStatus as B, type AnnouncementType as C, EFFECTIVE_SUBSCRIPTION_STATUSES as D, type EffectiveSubscriptionStatus as E, type FFIDSubscriptionStatus as F, FFIDAnnouncementBadge as G, FFIDAnnouncementList as H, type FFIDAnnouncementsError as I, type FFIDAnnouncementsErrorCode as J, type FFIDAnnouncementsServerResponse as K, type ListAnnouncementsOptions as L, type FFIDCacheConfig as M, type FFIDContextValue as N, type FFIDInquiryCategory as O, type FFIDInquiryCategorySite2026 as P, FFIDInquiryForm as Q, type FFIDInquiryFormCategoryItem as R, type FFIDInquiryFormClassNames as S, type FFIDInquiryFormLegalLayout as T, type FFIDInquiryFormOrganization as U, type FFIDInquiryFormPlaceholderContext as V, type FFIDInquiryFormPrefill as W, type FFIDInquiryFormProps as X, type FFIDInquiryFormSubmitData as Y, type FFIDInquiryFormSubmitResult as Z, type FFIDJwtClaims as _, type FFIDPrompt as a, type FFIDOAuthTokenResponse as a0, type FFIDOAuthUserInfoMemberRole as a1, FFIDOrganizationSwitcher as a2, type FFIDRedirectErrorCode as a3, type FFIDSeatModel as a4, type FFIDServiceAccessDenialReason as a5, type FFIDServiceAccessFailPolicy as a6, FFIDSubscriptionBadge as a7, type FFIDTokenIntrospectionResponse as a8, FFIDUserMenu as a9, FFID_INQUIRY_CATEGORIES as aa, FFID_INQUIRY_CATEGORIES_SITE_2026 as ab, type UseFFIDAnnouncementsOptions as ac, type UseFFIDAnnouncementsReturn as ad, isFFIDInquiryCategorySite2026 as ae, useFFIDAnnouncements as af, type FFIDAnnouncementBadgeClassNames as ag, type FFIDAnnouncementBadgeProps as ah, type FFIDAnnouncementListClassNames as ai, type FFIDAnnouncementListProps as aj, type FFIDLoginButtonProps as ak, type FFIDOrganizationSwitcherClassNames as al, type FFIDOrganizationSwitcherProps as am, type FFIDSubscriptionBadgeClassNames as an, type FFIDSubscriptionBadgeProps as ao, type FFIDUserMenuClassNames as ap, type FFIDUserMenuProps as aq, type FFIDConfig as b, type FFIDApiResponse as c, type FFIDSessionResponse as d, type FFIDRedirectResult as e, type FFIDError as f, type FFIDSubscriptionCheckResponse as g, type FFIDCheckServiceAccessParams as h, type FFIDServiceAccessDecision as i, type FFIDAnalyticsConfig as j, type FFIDVerifyAccessTokenOptions as k, type FFIDOAuthUserInfo as l, type FFIDInquiryCreateParams as m, type FFIDInquiryCreateResponse as n, type FFIDAuthMode as o, type FFIDLogger as p, type FFIDCacheAdapter as q, type FFIDUser as r, type FFIDOrganization as s, type FFIDSubscription as t, type FFIDSubscriptionContextValue as u, type FFIDOAuthUserInfoSubscription as v, type FFIDAnnouncementsClientConfig as w, type FFIDAnnouncementsApiResponse as x, type FFIDAnnouncementsLogger as y, type Announcement as z };
1526
+ export { type FFIDInquiryFormSubmitResult as $, type AnnouncementListResponse as A, type Announcement as B, type AnnouncementStatus as C, type AnnouncementType as D, type EffectiveSubscriptionStatus as E, type FFIDSubscriptionStatus as F, EFFECTIVE_SUBSCRIPTION_STATUSES as G, FFIDAnnouncementBadge as H, FFIDAnnouncementList as I, type FFIDAnnouncementsError as J, type FFIDAnnouncementsErrorCode as K, type ListAnnouncementsOptions as L, type FFIDAnnouncementsServerResponse as M, type FFIDApiResponseMeta as N, type FFIDCacheConfig as O, type FFIDContextValue as P, type FFIDInquiryCategory as Q, type FFIDInquiryCategorySite2026 as R, FFIDInquiryForm as S, type FFIDInquiryFormCategoryItem as T, type FFIDInquiryFormClassNames as U, type FFIDInquiryFormLegalLayout as V, type FFIDInquiryFormOrganization as W, type FFIDInquiryFormPlaceholderContext as X, type FFIDInquiryFormPrefill as Y, type FFIDInquiryFormProps as Z, type FFIDInquiryFormSubmitData as _, type FFIDPrompt as a, type FFIDJwtClaims as a0, FFIDLoginButton as a1, type FFIDOAuthTokenResponse as a2, type FFIDOAuthUserInfoMemberRole as a3, FFIDOrganizationSwitcher as a4, type FFIDRedirectErrorCode as a5, type FFIDSeatModel as a6, type FFIDServiceAccessDenialReason as a7, type FFIDServiceAccessFailPolicy as a8, FFIDSubscriptionBadge as a9, type FFIDTokenIntrospectionResponse as aa, FFIDUserMenu as ab, FFID_INQUIRY_CATEGORIES as ac, FFID_INQUIRY_CATEGORIES_SITE_2026 as ad, type UseFFIDAnnouncementsOptions as ae, type UseFFIDAnnouncementsReturn as af, isFFIDInquiryCategorySite2026 as ag, useFFIDAnnouncements as ah, type FFIDAnnouncementBadgeClassNames as ai, type FFIDAnnouncementBadgeProps as aj, type FFIDAnnouncementListClassNames as ak, type FFIDAnnouncementListProps as al, type FFIDLoginButtonProps as am, type FFIDOrganizationSwitcherClassNames as an, type FFIDOrganizationSwitcherProps as ao, type FFIDSubscriptionBadgeClassNames as ap, type FFIDSubscriptionBadgeProps as aq, type FFIDUserMenuClassNames as ar, type FFIDUserMenuProps as as, type FFIDConfig as b, type FFIDApiResponse as c, type FFIDSessionResponse as d, type FFIDSignOutResult as e, type FFIDRedirectResult as f, type FFIDError as g, type FFIDSubscriptionCheckResponse as h, type FFIDCheckServiceAccessParams as i, type FFIDServiceAccessDecision as j, type FFIDAnalyticsConfig as k, type FFIDVerifyAccessTokenOptions as l, type FFIDOAuthUserInfo as m, type FFIDInquiryCreateParams as n, type FFIDInquiryCreateResponse as o, type FFIDAuthMode as p, type FFIDLogger as q, type FFIDCacheAdapter as r, type FFIDUser as s, type FFIDOrganization as t, type FFIDSubscription as u, type FFIDSubscriptionContextValue as v, type FFIDOAuthUserInfoSubscription as w, type FFIDAnnouncementsClientConfig as x, type FFIDAnnouncementsApiResponse as y, type FFIDAnnouncementsLogger as z };
@@ -80,7 +80,8 @@ declare const EFFECTIVE_SUBSCRIPTION_STATUSES: readonly ["active", "active_cance
80
80
  * `src/lib/common/subscription-helpers.ts`, and a server-side unit test pins
81
81
  * element-equality between the two arrays (#3474) — convention-only sync
82
82
  * could drift silently in the server-extending direction (a new server
83
- * literal would fall through SDK consumers' `switch` defaults).
83
+ * literal would fall through SDK consumers' `switch` defaults). The PR gate also
84
+ * runs `npm run sdk:verify-sync` for SDK/server subscription changes.
84
85
  */
85
86
  type EffectiveSubscriptionStatus = (typeof EFFECTIVE_SUBSCRIPTION_STATUSES)[number];
86
87
 
@@ -658,6 +659,19 @@ interface FFIDSessionResponse {
658
659
  organizations: FFIDOrganization[];
659
660
  subscriptions: FFIDSubscription[];
660
661
  }
662
+ /**
663
+ * Optional metadata on successful {@link FFIDApiResponse} values (#4136).
664
+ *
665
+ * Present only on the success branch — error responses never carry `meta`.
666
+ */
667
+ interface FFIDApiResponseMeta {
668
+ /**
669
+ * Set when introspect-strategy verification could not use the configured
670
+ * cache (adapter read/write failure or `crypto.subtle` unavailable).
671
+ * Visible without a custom logger; absent when cache operated normally.
672
+ */
673
+ verificationCacheDegraded?: true;
674
+ }
661
675
  /**
662
676
  * API response wrapper (discriminated union for type safety)
663
677
  *
@@ -667,10 +681,33 @@ interface FFIDSessionResponse {
667
681
  type FFIDApiResponse<T> = {
668
682
  data: T;
669
683
  error?: undefined;
684
+ meta?: FFIDApiResponseMeta;
670
685
  } | {
671
686
  data?: undefined;
672
687
  error: FFIDError;
673
688
  };
689
+ /**
690
+ * Result of `signOut()` (#4119, extended #4136).
691
+ *
692
+ * Local credentials (tokens / local state) are always cleared when `signOut()`
693
+ * resolves without `error`. `revoked` additionally indicates whether the
694
+ * server-side revocation/sign-out actually succeeded:
695
+ *
696
+ * - `revoked: true` — no server-side session/token remains active.
697
+ * - `revoked: false` — server-side revocation failed (network error or non-2xx
698
+ * response). The access token may remain valid server-side until natural
699
+ * expiry. Non-fatal: the local sign-out still completed, but callers that
700
+ * need guaranteed revocation (e.g. shared-device flows) should surface this.
701
+ *
702
+ * Token mode (#4136): `accessTokenRevoked` / `refreshTokenRevoked` report each
703
+ * RFC 7009 revoke call. `revoked` is `true` only when every applicable token
704
+ * was revoked successfully. Cookie mode omits the per-token fields.
705
+ */
706
+ interface FFIDSignOutResult {
707
+ revoked: boolean;
708
+ accessTokenRevoked?: boolean;
709
+ refreshTokenRevoked?: boolean;
710
+ }
674
711
 
675
712
  /**
676
713
  * Response shape from `GET /api/v1/ext/analytics/config?service=<code>`.
@@ -704,23 +741,33 @@ interface FFIDAnalyticsConfig {
704
741
  * has been fired **3 times within 60 seconds**. Caller should surface a
705
742
  * manual "再度ログインする" UI rather than retry automatically (#2406 / #2411).
706
743
  *
707
- * SDK 2.18.0 only ships `'redirect_loop_detected'`. Other failure paths
708
- * (SSR environment, PKCE generation failure, empty organizationId) currently
709
- * return `error` without a `code`. New codes will be added in future minor
710
- * versions — treat this union as forward-extensible and do NOT exhaustively
711
- * `switch` over it without a `default` branch for consumer code that must
712
- * stay compatible across SDK upgrades.
744
+ * - `'state_persistence_failed'`: `redirectToAuthorize()` could not persist
745
+ * the OAuth CSRF `state` (storage unavailable / quota). Redirect is aborted
746
+ * fail-closed (#4136) callers should surface a manual retry UI.
747
+ *
748
+ * Other failure paths (SSR environment, PKCE generation failure, empty
749
+ * organizationId) currently return `error` without a `code`. Treat this union
750
+ * as forward-extensible and do NOT exhaustively `switch` over it without a
751
+ * `default` branch for consumer code that must stay compatible across SDK
752
+ * upgrades.
713
753
  */
714
- type FFIDRedirectErrorCode = 'redirect_loop_detected';
754
+ type FFIDRedirectErrorCode = 'redirect_loop_detected' | 'state_persistence_failed';
715
755
  /**
716
756
  * Result of a redirect operation (redirectToLogin / redirectToAuthorize / redirectToLogout)
717
757
  *
718
758
  * Structured return type so callers can inspect failure reasons
719
759
  * instead of receiving a bare `false`. When `code` is set, branch on it
720
760
  * for programmatic handling; otherwise log `error` for humans.
761
+ *
762
+ * `loopDetectionDisabled` (#4119): set to `true` when sessionStorage is
763
+ * unavailable (iOS WebKit private mode / eviction) so redirect-loop detection
764
+ * ran **fail-open** — the redirect fired, but repeated-redirect protection is
765
+ * disabled for this browser session. Callers that need loop protection on
766
+ * such browsers should add their own max-retry guard.
721
767
  */
722
768
  type FFIDRedirectResult = {
723
769
  success: true;
770
+ loopDetectionDisabled?: boolean;
724
771
  } | {
725
772
  success: false;
726
773
  error: string;
@@ -1476,4 +1523,4 @@ interface FFIDInquiryFormPlaceholderContext {
1476
1523
  }
1477
1524
  declare function FFIDInquiryForm({ mode, prefill, organizations, preselectedOrganizationId, categories, termsVersion, privacyVersion, termsHref, privacyHref, turnstileToken, turnstileSlot, onSubmit, onChange, legalLayout, messagePlaceholder, requireCategorySelection, unstyled, classNames, locale, className, }: FFIDInquiryFormProps): react_jsx_runtime.JSX.Element;
1478
1525
 
1479
- export { FFIDLoginButton as $, type AnnouncementListResponse as A, type AnnouncementStatus as B, type AnnouncementType as C, EFFECTIVE_SUBSCRIPTION_STATUSES as D, type EffectiveSubscriptionStatus as E, type FFIDSubscriptionStatus as F, FFIDAnnouncementBadge as G, FFIDAnnouncementList as H, type FFIDAnnouncementsError as I, type FFIDAnnouncementsErrorCode as J, type FFIDAnnouncementsServerResponse as K, type ListAnnouncementsOptions as L, type FFIDCacheConfig as M, type FFIDContextValue as N, type FFIDInquiryCategory as O, type FFIDInquiryCategorySite2026 as P, FFIDInquiryForm as Q, type FFIDInquiryFormCategoryItem as R, type FFIDInquiryFormClassNames as S, type FFIDInquiryFormLegalLayout as T, type FFIDInquiryFormOrganization as U, type FFIDInquiryFormPlaceholderContext as V, type FFIDInquiryFormPrefill as W, type FFIDInquiryFormProps as X, type FFIDInquiryFormSubmitData as Y, type FFIDInquiryFormSubmitResult as Z, type FFIDJwtClaims as _, type FFIDPrompt as a, type FFIDOAuthTokenResponse as a0, type FFIDOAuthUserInfoMemberRole as a1, FFIDOrganizationSwitcher as a2, type FFIDRedirectErrorCode as a3, type FFIDSeatModel as a4, type FFIDServiceAccessDenialReason as a5, type FFIDServiceAccessFailPolicy as a6, FFIDSubscriptionBadge as a7, type FFIDTokenIntrospectionResponse as a8, FFIDUserMenu as a9, FFID_INQUIRY_CATEGORIES as aa, FFID_INQUIRY_CATEGORIES_SITE_2026 as ab, type UseFFIDAnnouncementsOptions as ac, type UseFFIDAnnouncementsReturn as ad, isFFIDInquiryCategorySite2026 as ae, useFFIDAnnouncements as af, type FFIDAnnouncementBadgeClassNames as ag, type FFIDAnnouncementBadgeProps as ah, type FFIDAnnouncementListClassNames as ai, type FFIDAnnouncementListProps as aj, type FFIDLoginButtonProps as ak, type FFIDOrganizationSwitcherClassNames as al, type FFIDOrganizationSwitcherProps as am, type FFIDSubscriptionBadgeClassNames as an, type FFIDSubscriptionBadgeProps as ao, type FFIDUserMenuClassNames as ap, type FFIDUserMenuProps as aq, type FFIDConfig as b, type FFIDApiResponse as c, type FFIDSessionResponse as d, type FFIDRedirectResult as e, type FFIDError as f, type FFIDSubscriptionCheckResponse as g, type FFIDCheckServiceAccessParams as h, type FFIDServiceAccessDecision as i, type FFIDAnalyticsConfig as j, type FFIDVerifyAccessTokenOptions as k, type FFIDOAuthUserInfo as l, type FFIDInquiryCreateParams as m, type FFIDInquiryCreateResponse as n, type FFIDAuthMode as o, type FFIDLogger as p, type FFIDCacheAdapter as q, type FFIDUser as r, type FFIDOrganization as s, type FFIDSubscription as t, type FFIDSubscriptionContextValue as u, type FFIDOAuthUserInfoSubscription as v, type FFIDAnnouncementsClientConfig as w, type FFIDAnnouncementsApiResponse as x, type FFIDAnnouncementsLogger as y, type Announcement as z };
1526
+ export { type FFIDInquiryFormSubmitResult as $, type AnnouncementListResponse as A, type Announcement as B, type AnnouncementStatus as C, type AnnouncementType as D, type EffectiveSubscriptionStatus as E, type FFIDSubscriptionStatus as F, EFFECTIVE_SUBSCRIPTION_STATUSES as G, FFIDAnnouncementBadge as H, FFIDAnnouncementList as I, type FFIDAnnouncementsError as J, type FFIDAnnouncementsErrorCode as K, type ListAnnouncementsOptions as L, type FFIDAnnouncementsServerResponse as M, type FFIDApiResponseMeta as N, type FFIDCacheConfig as O, type FFIDContextValue as P, type FFIDInquiryCategory as Q, type FFIDInquiryCategorySite2026 as R, FFIDInquiryForm as S, type FFIDInquiryFormCategoryItem as T, type FFIDInquiryFormClassNames as U, type FFIDInquiryFormLegalLayout as V, type FFIDInquiryFormOrganization as W, type FFIDInquiryFormPlaceholderContext as X, type FFIDInquiryFormPrefill as Y, type FFIDInquiryFormProps as Z, type FFIDInquiryFormSubmitData as _, type FFIDPrompt as a, type FFIDJwtClaims as a0, FFIDLoginButton as a1, type FFIDOAuthTokenResponse as a2, type FFIDOAuthUserInfoMemberRole as a3, FFIDOrganizationSwitcher as a4, type FFIDRedirectErrorCode as a5, type FFIDSeatModel as a6, type FFIDServiceAccessDenialReason as a7, type FFIDServiceAccessFailPolicy as a8, FFIDSubscriptionBadge as a9, type FFIDTokenIntrospectionResponse as aa, FFIDUserMenu as ab, FFID_INQUIRY_CATEGORIES as ac, FFID_INQUIRY_CATEGORIES_SITE_2026 as ad, type UseFFIDAnnouncementsOptions as ae, type UseFFIDAnnouncementsReturn as af, isFFIDInquiryCategorySite2026 as ag, useFFIDAnnouncements as ah, type FFIDAnnouncementBadgeClassNames as ai, type FFIDAnnouncementBadgeProps as aj, type FFIDAnnouncementListClassNames as ak, type FFIDAnnouncementListProps as al, type FFIDLoginButtonProps as am, type FFIDOrganizationSwitcherClassNames as an, type FFIDOrganizationSwitcherProps as ao, type FFIDSubscriptionBadgeClassNames as ap, type FFIDSubscriptionBadgeProps as aq, type FFIDUserMenuClassNames as ar, type FFIDUserMenuProps as as, type FFIDConfig as b, type FFIDApiResponse as c, type FFIDSessionResponse as d, type FFIDSignOutResult as e, type FFIDRedirectResult as f, type FFIDError as g, type FFIDSubscriptionCheckResponse as h, type FFIDCheckServiceAccessParams as i, type FFIDServiceAccessDecision as j, type FFIDAnalyticsConfig as k, type FFIDVerifyAccessTokenOptions as l, type FFIDOAuthUserInfo as m, type FFIDInquiryCreateParams as n, type FFIDInquiryCreateResponse as o, type FFIDAuthMode as p, type FFIDLogger as q, type FFIDCacheAdapter as r, type FFIDUser as s, type FFIDOrganization as t, type FFIDSubscription as u, type FFIDSubscriptionContextValue as v, type FFIDOAuthUserInfoSubscription as w, type FFIDAnnouncementsClientConfig as x, type FFIDAnnouncementsApiResponse as y, type FFIDAnnouncementsLogger as z };