@feelflow/ffid-sdk 10.0.0 → 11.0.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.
@@ -961,12 +961,19 @@ interface FFIDBuyCreditsUrlParams {
961
961
  type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
962
962
  interface FFIDSubscriptionCheckResponse {
963
963
  hasActiveSubscription: boolean;
964
+ /**
965
+ * Active seat for the requested user; null for organization-only checks.
966
+ * Older servers omit this field. User access requires hasAccess AND
967
+ * seatAssigned === true; an omitted/null value is not proof of a seat.
968
+ */
969
+ seatAssigned?: boolean | null;
964
970
  /**
965
971
  * Canonical access decision returned by FFID's `/subscriptions/ext/check`.
966
972
  *
967
973
  * This is the server-side source of truth for service gates. Consumers
968
974
  * should not recompute access from `currentPeriodEnd`, `past_due_since`, or
969
975
  * local payment timestamps.
976
+ * This is contract access; user access also requires seatAssigned === true.
970
977
  */
971
978
  hasAccess?: boolean;
972
979
  /** True when `effectiveStatus === 'past_due_grace'`. */
@@ -996,9 +1003,11 @@ interface FFIDSubscriptionCheckResponse {
996
1003
  */
997
1004
  pricingModel?: FFIDPricingModel | null;
998
1005
  /**
999
- * Credit balance summary — flat plans only (10.0.0). `null` for per_seat, for no
1000
- * subscription, **and** when FFID could not read the ledger, so `null` does not
1001
- * mean "not flat" (use `pricingModel`). Never affects `hasAccess`.
1006
+ * Credit balance summary — paid flat plans only (10.0.0). `null` for per_seat, for a
1007
+ * `free` plan (flat on the unified ladder since #6547, but outside credits — consume /
1008
+ * balance return 409 `CREDITS_NOT_APPLICABLE`), for no subscription, **and** when FFID
1009
+ * could not read the ledger, so `null` does not mean "not flat" (use `pricingModel`).
1010
+ * Never affects `hasAccess`.
1002
1011
  */
1003
1012
  credits?: FFIDSubscriptionCheckCredits | null;
1004
1013
  /**
@@ -1014,7 +1023,8 @@ type FFIDServiceAccessFailPolicy = 'failClosed';
1014
1023
  *
1015
1024
  * `member_limit_reached` (10.0.0) is FFID's denial reason when a flat plan's member
1016
1025
  * limit is full and the user has no seat. It reaches you through OAuth
1017
- * (`denial_reason` on authorize / userinfo / introspect); `checkServiceAccess()`
1026
+ * (`denial_reason` on the authorize redirect / userinfo 403; see
1027
+ * `FFIDOAuthDenialReason` for that vocabulary); `checkServiceAccess()`
1018
1028
  * derives its decision from `effectiveStatus` and never returns it, because a full
1019
1029
  * member limit does not change `hasAccess` (CREDITS_API §1-5). It is in this union so
1020
1030
  * one exhaustive `switch` over denial reasons covers both paths.
@@ -1044,7 +1054,10 @@ interface FFIDServiceAccessError {
1044
1054
  details?: unknown;
1045
1055
  }
1046
1056
  interface FFIDServiceAccessDecision {
1057
+ /** Contract access; user access also requires seatAssigned === true. */
1047
1058
  hasAccess: boolean;
1059
+ /** User's active seat, passed through when returned. Gate user access with === true. */
1060
+ seatAssigned?: boolean | null;
1048
1061
  effectiveStatus: EffectiveSubscriptionStatus | null;
1049
1062
  isGrace: boolean;
1050
1063
  isBlocked: boolean;
@@ -1209,9 +1222,18 @@ interface FFIDAddMemberRequest {
1209
1222
  interface FFIDAddMemberParams extends FFIDAddMemberRequest {
1210
1223
  organizationId: string;
1211
1224
  }
1225
+ /** Seat assignment outcome after membership creation; membership exists in every case. */
1226
+ type FFIDMemberSeatAssignmentResult = 'assigned' | 'not_applicable' | 'member_limit_reached' | 'failed';
1212
1227
  /** Response from addMember (ext) */
1213
1228
  interface FFIDAddMemberResponse {
1214
1229
  member: FFIDOrganizationMember;
1230
+ /**
1231
+ * Membership creation can succeed even when seat assignment fails.
1232
+ * Omitted by older servers. `not_applicable`/undefined do not prove an active seat.
1233
+ * Check the authenticated user's hasAccess and seatAssigned before granting access;
1234
+ * do not automatically restore a removed seat on a duplicate-member retry.
1235
+ */
1236
+ seatAssignment?: FFIDMemberSeatAssignmentResult;
1215
1237
  }
1216
1238
  /** Response from updateMemberRole (ext) */
1217
1239
  interface FFIDUpdateMemberRoleResponse {
@@ -2430,11 +2452,10 @@ interface FFIDConfig {
2430
2452
  */
2431
2453
  cache?: FFIDCacheConfig | undefined;
2432
2454
  /**
2433
- * Request timeout in milliseconds for FFID API calls. Applies to server-side
2434
- * token verification / introspection and, in `token` mode, to the client-side
2435
- * OAuth operations (code exchange / refresh / revoke) — including via the
2436
- * `FFIDProvider` `timeout` prop (#4260). On timeout the fetch is aborted and
2437
- * surfaced through the normal error path (e.g. `NETWORK_ERROR`).
2455
+ * Per-HTTP timeout (ms): shared JSON APIs (e.g. checkSubscription/getProfile),
2456
+ * token verification/introspection, token OAuth exchange/refresh/revoke; also FFIDProvider.timeout.
2457
+ * Shared JSON includes body and preserves signals; refresh/retry have separate deadlines.
2458
+ * Excludes token getSession, cookie signOut, public/newsletter/inquiry; not a method deadline.
2438
2459
  * @default undefined (no timeout, uses fetch default)
2439
2460
  */
2440
2461
  timeout?: number | undefined;
@@ -2800,6 +2821,7 @@ declare function createFFIDClient(config: FFIDConfig): {
2800
2821
  organizationId: string;
2801
2822
  email: string;
2802
2823
  role?: FFIDAssignableMemberRole;
2824
+ inviterUserId?: string;
2803
2825
  }) => Promise<FFIDApiResponse<FFIDInviteMemberResponse>>;
2804
2826
  leaveOrganization: (params: FFIDLeaveOrganizationParams) => Promise<FFIDApiResponse<FFIDLeaveOrganizationResponse>>;
2805
2827
  getAnalyticsConfig: (serviceCode: string, options?: FFIDProfileCallOptions) => Promise<FFIDApiResponse<FFIDAnalyticsConfig>>;
@@ -2886,4 +2908,4 @@ declare function createFFIDClient(config: FFIDConfig): {
2886
2908
  /** Type of the FFID client */
2887
2909
  type FFIDClient = ReturnType<typeof createFFIDClient>;
2888
2910
 
2889
- export { type FFIDProvisionedOrganization as $, type FFIDOrganization as A, type FFIDOrganizationLogoUploadResponse as B, type FFIDOrganizationMember as C, type FFIDOrganizationProfile as D, type FFIDOrganizationProfileErrorCode as E, type FFIDLogger as F, type FFIDOrganizationProfileResponse as G, type FFIDOtpSendResponse as H, type FFIDOtpVerifyResponse as I, type FFIDPasswordResetConfirmResponse as J, type FFIDPasswordResetResponse as K, type FFIDPasswordResetVerifyResponse as L, type FFIDProfileCallOptions as M, type FFIDProvisionMemberPlan as N, type FFIDProvisionMemberPlanStatus as O, type FFIDProvisionMemberResult as P, type FFIDProvisionMemberStatus as Q, type FFIDProvisionOrganizationDryRun as R, type FFIDProvisionOrganizationMemberInput as S, type FFIDProvisionOrganizationOutcome as T, type FFIDProvisionOrganizationParams as U, type FFIDProvisionOrganizationResponse as V, type FFIDProvisionUserDryRun as W, type FFIDProvisionUserOutcome as X, type FFIDProvisionUserParams as Y, type FFIDProvisionUserProfileInput as Z, type FFIDProvisionUserResponse as _, type FFIDError as a, type FFIDProvisionedUser as a0, type FFIDPublishedPlan as a1, type FFIDRemoveMemberResponse as a2, type FFIDResetSessionResponse as a3, type FFIDSubscription as a4, type FFIDUpdateMemberRoleResponse as a5, type FFIDUpdateUserProfileRequest as a6, type FFIDUploadOrganizationLogoParams as a7, type FFIDUpsertOrganizationProfileParams as a8, type FFIDUpsertOrganizationProfileRequest as a9, type FFIDUser as aa, type FFIDUserProfile as ab, FFID_ALLOWED_ORGANIZATION_LOGO_MIME_TYPES as ac, FFID_CATALOG_ENVIRONMENTS as ad, FFID_CATALOG_PUBLICATION_STATUSES as ae, FFID_COMPANY_SIZE_CODES as af, FFID_INDUSTRY_CODES as ag, FFID_MAX_ORGANIZATION_LOGO_FILE_SIZE_BYTES as ah, FFID_MAX_ORGANIZATION_LOGO_FILE_SIZE_MB as ai, FFID_ORGANIZATION_PROFILE_ERROR_CODES as aj, type TokenData as ak, type TokenStore as al, createFFIDClient as am, createTokenStore as an, type FFIDCacheAdapter as b, type FFIDVerifyAccessTokenOptions as c, type FFIDApiResponse as d, type FFIDOAuthUserInfo as e, type FFIDCatalogEnvironment as f, type FFIDBillingInterval as g, type FFIDTaxBehavior as h, type FFIDPublishedCatalog as i, type FFIDAddMemberParams as j, type FFIDAddMemberRequest as k, type FFIDAddMemberResponse as l, type FFIDAllowedLogoMimeType as m, type FFIDAssignableMemberRole as n, type FFIDCacheConfig as o, type FFIDCatalogPublication as p, type FFIDCatalogPublicationStatus as q, type FFIDClient as r, type FFIDCompanySizeCode as s, type FFIDConfig as t, type FFIDIndustryCode as u, type FFIDListMembersResponse as v, type FFIDListingConsentInput as w, type FFIDLogoWallEntry as x, type FFIDLogoWallResponse as y, type FFIDMemberRole as z };
2911
+ export { type FFIDProvisionUserResponse as $, type FFIDMemberSeatAssignmentResult as A, type FFIDOrganization as B, type FFIDOrganizationLogoUploadResponse as C, type FFIDOrganizationMember as D, type FFIDOrganizationProfile as E, type FFIDError as F, type FFIDOrganizationProfileErrorCode as G, type FFIDOrganizationProfileResponse as H, type FFIDOtpSendResponse as I, type FFIDOtpVerifyResponse as J, type FFIDPasswordResetConfirmResponse as K, type FFIDPasswordResetResponse as L, type FFIDPasswordResetVerifyResponse as M, type FFIDProfileCallOptions as N, type FFIDProvisionMemberPlan as O, type FFIDProvisionMemberPlanStatus as P, type FFIDProvisionMemberResult as Q, type FFIDProvisionMemberStatus as R, type FFIDProvisionOrganizationDryRun as S, type FFIDProvisionOrganizationMemberInput as T, type FFIDProvisionOrganizationOutcome as U, type FFIDProvisionOrganizationParams as V, type FFIDProvisionOrganizationResponse as W, type FFIDProvisionUserDryRun as X, type FFIDProvisionUserOutcome as Y, type FFIDProvisionUserParams as Z, type FFIDProvisionUserProfileInput as _, type FFIDLogger as a, type FFIDProvisionedOrganization as a0, type FFIDProvisionedUser as a1, type FFIDPublishedPlan as a2, type FFIDRemoveMemberResponse as a3, type FFIDResetSessionResponse as a4, type FFIDSubscription as a5, type FFIDUpdateMemberRoleResponse as a6, type FFIDUpdateUserProfileRequest as a7, type FFIDUploadOrganizationLogoParams as a8, type FFIDUpsertOrganizationProfileParams as a9, type FFIDUpsertOrganizationProfileRequest as aa, type FFIDUser as ab, type FFIDUserProfile as ac, FFID_ALLOWED_ORGANIZATION_LOGO_MIME_TYPES as ad, FFID_CATALOG_ENVIRONMENTS as ae, FFID_CATALOG_PUBLICATION_STATUSES as af, FFID_COMPANY_SIZE_CODES as ag, FFID_INDUSTRY_CODES as ah, FFID_MAX_ORGANIZATION_LOGO_FILE_SIZE_BYTES as ai, FFID_MAX_ORGANIZATION_LOGO_FILE_SIZE_MB as aj, FFID_ORGANIZATION_PROFILE_ERROR_CODES as ak, type TokenData as al, type TokenStore as am, createFFIDClient as an, createTokenStore as ao, type FFIDCacheAdapter as b, type FFIDVerifyAccessTokenOptions as c, type FFIDApiResponse as d, type FFIDOAuthUserInfo as e, type FFIDCatalogEnvironment as f, type FFIDBillingInterval as g, type FFIDTaxBehavior as h, type FFIDPublishedCatalog as i, type FFIDAddMemberParams as j, type FFIDAddMemberRequest as k, type FFIDAddMemberResponse as l, type FFIDAllowedLogoMimeType as m, type FFIDAssignableMemberRole as n, type FFIDCacheConfig as o, type FFIDCatalogPublication as p, type FFIDCatalogPublicationStatus as q, type FFIDClient as r, type FFIDCompanySizeCode as s, type FFIDConfig as t, type FFIDIndustryCode as u, type FFIDListMembersResponse as v, type FFIDListingConsentInput as w, type FFIDLogoWallEntry as x, type FFIDLogoWallResponse as y, type FFIDMemberRole as z };
@@ -909,12 +909,19 @@ interface FFIDBuyCreditsUrlParams {
909
909
  type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
910
910
  interface FFIDSubscriptionCheckResponse {
911
911
  hasActiveSubscription: boolean;
912
+ /**
913
+ * Active seat for the requested user; null for organization-only checks.
914
+ * Older servers omit this field. User access requires hasAccess AND
915
+ * seatAssigned === true; an omitted/null value is not proof of a seat.
916
+ */
917
+ seatAssigned?: boolean | null;
912
918
  /**
913
919
  * Canonical access decision returned by FFID's `/subscriptions/ext/check`.
914
920
  *
915
921
  * This is the server-side source of truth for service gates. Consumers
916
922
  * should not recompute access from `currentPeriodEnd`, `past_due_since`, or
917
923
  * local payment timestamps.
924
+ * This is contract access; user access also requires seatAssigned === true.
918
925
  */
919
926
  hasAccess?: boolean;
920
927
  /** True when `effectiveStatus === 'past_due_grace'`. */
@@ -944,9 +951,11 @@ interface FFIDSubscriptionCheckResponse {
944
951
  */
945
952
  pricingModel?: FFIDPricingModel | null;
946
953
  /**
947
- * Credit balance summary — flat plans only (10.0.0). `null` for per_seat, for no
948
- * subscription, **and** when FFID could not read the ledger, so `null` does not
949
- * mean "not flat" (use `pricingModel`). Never affects `hasAccess`.
954
+ * Credit balance summary — paid flat plans only (10.0.0). `null` for per_seat, for a
955
+ * `free` plan (flat on the unified ladder since #6547, but outside credits — consume /
956
+ * balance return 409 `CREDITS_NOT_APPLICABLE`), for no subscription, **and** when FFID
957
+ * could not read the ledger, so `null` does not mean "not flat" (use `pricingModel`).
958
+ * Never affects `hasAccess`.
950
959
  */
951
960
  credits?: FFIDSubscriptionCheckCredits | null;
952
961
  /**
@@ -962,7 +971,8 @@ type FFIDServiceAccessFailPolicy = 'failClosed';
962
971
  *
963
972
  * `member_limit_reached` (10.0.0) is FFID's denial reason when a flat plan's member
964
973
  * limit is full and the user has no seat. It reaches you through OAuth
965
- * (`denial_reason` on authorize / userinfo / introspect); `checkServiceAccess()`
974
+ * (`denial_reason` on the authorize redirect / userinfo 403; see
975
+ * `FFIDOAuthDenialReason` for that vocabulary); `checkServiceAccess()`
966
976
  * derives its decision from `effectiveStatus` and never returns it, because a full
967
977
  * member limit does not change `hasAccess` (CREDITS_API §1-5). It is in this union so
968
978
  * one exhaustive `switch` over denial reasons covers both paths.
@@ -992,7 +1002,10 @@ interface FFIDServiceAccessError {
992
1002
  details?: unknown;
993
1003
  }
994
1004
  interface FFIDServiceAccessDecision {
1005
+ /** Contract access; user access also requires seatAssigned === true. */
995
1006
  hasAccess: boolean;
1007
+ /** User's active seat, passed through when returned. Gate user access with === true. */
1008
+ seatAssigned?: boolean | null;
996
1009
  effectiveStatus: EffectiveSubscriptionStatus | null;
997
1010
  isGrace: boolean;
998
1011
  isBlocked: boolean;
@@ -1350,11 +1363,10 @@ interface FFIDConfig {
1350
1363
  */
1351
1364
  cache?: FFIDCacheConfig | undefined;
1352
1365
  /**
1353
- * Request timeout in milliseconds for FFID API calls. Applies to server-side
1354
- * token verification / introspection and, in `token` mode, to the client-side
1355
- * OAuth operations (code exchange / refresh / revoke) — including via the
1356
- * `FFIDProvider` `timeout` prop (#4260). On timeout the fetch is aborted and
1357
- * surfaced through the normal error path (e.g. `NETWORK_ERROR`).
1366
+ * Per-HTTP timeout (ms): shared JSON APIs (e.g. checkSubscription/getProfile),
1367
+ * token verification/introspection, token OAuth exchange/refresh/revoke; also FFIDProvider.timeout.
1368
+ * Shared JSON includes body and preserves signals; refresh/retry have separate deadlines.
1369
+ * Excludes token getSession, cookie signOut, public/newsletter/inquiry; not a method deadline.
1358
1370
  * @default undefined (no timeout, uses fetch default)
1359
1371
  */
1360
1372
  timeout?: number | undefined;
@@ -909,12 +909,19 @@ interface FFIDBuyCreditsUrlParams {
909
909
  type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
910
910
  interface FFIDSubscriptionCheckResponse {
911
911
  hasActiveSubscription: boolean;
912
+ /**
913
+ * Active seat for the requested user; null for organization-only checks.
914
+ * Older servers omit this field. User access requires hasAccess AND
915
+ * seatAssigned === true; an omitted/null value is not proof of a seat.
916
+ */
917
+ seatAssigned?: boolean | null;
912
918
  /**
913
919
  * Canonical access decision returned by FFID's `/subscriptions/ext/check`.
914
920
  *
915
921
  * This is the server-side source of truth for service gates. Consumers
916
922
  * should not recompute access from `currentPeriodEnd`, `past_due_since`, or
917
923
  * local payment timestamps.
924
+ * This is contract access; user access also requires seatAssigned === true.
918
925
  */
919
926
  hasAccess?: boolean;
920
927
  /** True when `effectiveStatus === 'past_due_grace'`. */
@@ -944,9 +951,11 @@ interface FFIDSubscriptionCheckResponse {
944
951
  */
945
952
  pricingModel?: FFIDPricingModel | null;
946
953
  /**
947
- * Credit balance summary — flat plans only (10.0.0). `null` for per_seat, for no
948
- * subscription, **and** when FFID could not read the ledger, so `null` does not
949
- * mean "not flat" (use `pricingModel`). Never affects `hasAccess`.
954
+ * Credit balance summary — paid flat plans only (10.0.0). `null` for per_seat, for a
955
+ * `free` plan (flat on the unified ladder since #6547, but outside credits — consume /
956
+ * balance return 409 `CREDITS_NOT_APPLICABLE`), for no subscription, **and** when FFID
957
+ * could not read the ledger, so `null` does not mean "not flat" (use `pricingModel`).
958
+ * Never affects `hasAccess`.
950
959
  */
951
960
  credits?: FFIDSubscriptionCheckCredits | null;
952
961
  /**
@@ -962,7 +971,8 @@ type FFIDServiceAccessFailPolicy = 'failClosed';
962
971
  *
963
972
  * `member_limit_reached` (10.0.0) is FFID's denial reason when a flat plan's member
964
973
  * limit is full and the user has no seat. It reaches you through OAuth
965
- * (`denial_reason` on authorize / userinfo / introspect); `checkServiceAccess()`
974
+ * (`denial_reason` on the authorize redirect / userinfo 403; see
975
+ * `FFIDOAuthDenialReason` for that vocabulary); `checkServiceAccess()`
966
976
  * derives its decision from `effectiveStatus` and never returns it, because a full
967
977
  * member limit does not change `hasAccess` (CREDITS_API §1-5). It is in this union so
968
978
  * one exhaustive `switch` over denial reasons covers both paths.
@@ -992,7 +1002,10 @@ interface FFIDServiceAccessError {
992
1002
  details?: unknown;
993
1003
  }
994
1004
  interface FFIDServiceAccessDecision {
1005
+ /** Contract access; user access also requires seatAssigned === true. */
995
1006
  hasAccess: boolean;
1007
+ /** User's active seat, passed through when returned. Gate user access with === true. */
1008
+ seatAssigned?: boolean | null;
996
1009
  effectiveStatus: EffectiveSubscriptionStatus | null;
997
1010
  isGrace: boolean;
998
1011
  isBlocked: boolean;
@@ -1350,11 +1363,10 @@ interface FFIDConfig {
1350
1363
  */
1351
1364
  cache?: FFIDCacheConfig | undefined;
1352
1365
  /**
1353
- * Request timeout in milliseconds for FFID API calls. Applies to server-side
1354
- * token verification / introspection and, in `token` mode, to the client-side
1355
- * OAuth operations (code exchange / refresh / revoke) — including via the
1356
- * `FFIDProvider` `timeout` prop (#4260). On timeout the fetch is aborted and
1357
- * surfaced through the normal error path (e.g. `NETWORK_ERROR`).
1366
+ * Per-HTTP timeout (ms): shared JSON APIs (e.g. checkSubscription/getProfile),
1367
+ * token verification/introspection, token OAuth exchange/refresh/revoke; also FFIDProvider.timeout.
1368
+ * Shared JSON includes body and preserves signals; refresh/retry have separate deadlines.
1369
+ * Excludes token getSession, cookie signOut, public/newsletter/inquiry; not a method deadline.
1358
1370
  * @default undefined (no timeout, uses fetch default)
1359
1371
  */
1360
1372
  timeout?: number | undefined;