@feelflow/ffid-sdk 10.1.0 → 12.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.
@@ -304,6 +304,9 @@ var OAUTH_INTROSPECT_ENDPOINT = "/api/v1/oauth/introspect";
304
304
  var CACHE_KEY_PREFIX = "ffid:introspect:";
305
305
  var HEX_BASE = 16;
306
306
  var HEX_BYTE_WIDTH = 2;
307
+ var HTTP_TOO_MANY_REQUESTS = 429;
308
+ var HTTP_SERVER_ERROR_MIN = 500;
309
+ var HTTP_SERVER_ERROR_LIMIT = 600;
307
310
  function createVerifyAccessToken(deps) {
308
311
  const { authMode, baseUrl, serviceCode, serviceApiKey, verifyStrategy, logger, createError, errorCodes, cache, timeout } = deps;
309
312
  let jwtVerify2 = null;
@@ -358,6 +361,16 @@ function createVerifyAccessToken(deps) {
358
361
  }
359
362
  return verifyViaIntrospect(accessToken);
360
363
  }
364
+ function introspectionUnavailable(status) {
365
+ logger.error("Token introspection unavailable", { status });
366
+ return {
367
+ error: {
368
+ code: errorCodes.NETWORK_ERROR,
369
+ message: `\u30C8\u30FC\u30AF\u30F3\u691C\u8A3C\u30B5\u30FC\u30D3\u30B9\u304C\u4E00\u6642\u7684\u306B\u5229\u7528\u3067\u304D\u307E\u305B\u3093 (status: ${status})`,
370
+ details: { status }
371
+ }
372
+ };
373
+ }
361
374
  async function verifyViaIntrospect(accessToken, cacheKeySuffix) {
362
375
  if (!serviceApiKey) {
363
376
  return {
@@ -415,10 +428,12 @@ function createVerifyAccessToken(deps) {
415
428
  }
416
429
  };
417
430
  }
431
+ const upstreamUnavailable = response.status === HTTP_TOO_MANY_REQUESTS || response.status >= HTTP_SERVER_ERROR_MIN && response.status < HTTP_SERVER_ERROR_LIMIT;
418
432
  let introspectResponse;
419
433
  try {
420
434
  introspectResponse = await response.json();
421
435
  } catch (parseError) {
436
+ if (upstreamUnavailable) return introspectionUnavailable(response.status);
422
437
  logger.error("Parse error during token verification:", parseError);
423
438
  return {
424
439
  error: {
@@ -427,6 +442,7 @@ function createVerifyAccessToken(deps) {
427
442
  }
428
443
  };
429
444
  }
445
+ if (upstreamUnavailable) return introspectionUnavailable(response.status);
430
446
  if (!response.ok) {
431
447
  const errorBody = introspectResponse;
432
448
  return {
@@ -1370,7 +1386,7 @@ var FFID_ORGANIZATION_PROFILE_ERROR_CODES = {
1370
1386
  };
1371
1387
 
1372
1388
  // src/client/version-check.ts
1373
- var SDK_VERSION = "10.1.0";
1389
+ var SDK_VERSION = "12.0.0";
1374
1390
  var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
1375
1391
  var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
1376
1392
  function sdkHeaders() {
@@ -1938,7 +1954,7 @@ function createInviteMethods(deps) {
1938
1954
  }).toString();
1939
1955
  return fetchWithAuth(`${EXT_INVITE_ENDPOINT}?${query}`, {
1940
1956
  method: "POST",
1941
- body: JSON.stringify({ email: params.email, role: params.role })
1957
+ body: JSON.stringify({ email: params.email, role: params.role, inviterUserId: params.inviterUserId })
1942
1958
  });
1943
1959
  }
1944
1960
  return { inviteMember };
@@ -2241,6 +2257,25 @@ function createOAuthTokenMethods(deps) {
2241
2257
  return { exchangeCodeForTokens, refreshAccessToken, signOutToken };
2242
2258
  }
2243
2259
 
2260
+ // src/client/request-timeout.ts
2261
+ function withRequestTimeout(options, timeout) {
2262
+ if (timeout === void 0 || options.signal?.aborted) return options;
2263
+ const deadline = AbortSignal.timeout(timeout);
2264
+ if (!options.signal) return { ...options, signal: deadline };
2265
+ const callerSignal = options.signal;
2266
+ const controller = new AbortController();
2267
+ const abortFromCaller = () => abort(callerSignal.reason);
2268
+ const abortFromDeadline = () => abort(deadline.reason);
2269
+ function abort(reason) {
2270
+ callerSignal.removeEventListener("abort", abortFromCaller);
2271
+ deadline.removeEventListener("abort", abortFromDeadline);
2272
+ controller.abort(reason);
2273
+ }
2274
+ callerSignal.addEventListener("abort", abortFromCaller, { once: true });
2275
+ deadline.addEventListener("abort", abortFromDeadline, { once: true });
2276
+ return { ...options, signal: controller.signal };
2277
+ }
2278
+
2244
2279
  // src/client/session.ts
2245
2280
  var SESSION_ENDPOINT = "/api/v1/auth/session";
2246
2281
  var LOGOUT_ENDPOINT = "/api/v1/auth/signout";
@@ -3759,6 +3794,7 @@ function toServiceAccessDecision(response, allowGrace) {
3759
3794
  const isBlocked = response.isBlocked ?? (effectiveStatus === null || effectiveStatus !== null && BLOCKING_EFFECTIVE_STATUSES.includes(effectiveStatus));
3760
3795
  return {
3761
3796
  hasAccess,
3797
+ ...response.seatAssigned !== void 0 ? { seatAssigned: response.seatAssigned } : {},
3762
3798
  effectiveStatus,
3763
3799
  isGrace,
3764
3800
  isBlocked: isBlocked || !hasAccess,
@@ -3965,9 +4001,10 @@ function createFFIDClient(config) {
3965
4001
  async function fetchWithAuth(endpoint, options = {}, authOverride) {
3966
4002
  const url = `${baseUrl}${endpoint}`;
3967
4003
  logger.debug("Fetching:", url);
3968
- const fetchOptions = buildFetchOptions(options, authOverride);
4004
+ let fetchOptions = buildFetchOptions(options, authOverride);
3969
4005
  let response;
3970
4006
  try {
4007
+ fetchOptions = withRequestTimeout(fetchOptions, timeout);
3971
4008
  response = await fetch(url, fetchOptions);
3972
4009
  } catch (error) {
3973
4010
  logger.error("Network error:", error);
@@ -3982,9 +4019,9 @@ function createFFIDClient(config) {
3982
4019
  const refreshResult = await refreshAccessToken();
3983
4020
  if (!refreshResult.error) {
3984
4021
  logger.debug("Token refreshed, retrying request");
3985
- const retryOptions = buildFetchOptions(options);
3986
4022
  try {
3987
- response = await fetch(url, retryOptions);
4023
+ fetchOptions = withRequestTimeout(buildFetchOptions(options), timeout);
4024
+ response = await fetch(url, fetchOptions);
3988
4025
  } catch (retryError) {
3989
4026
  logger.error("Network error on retry:", retryError);
3990
4027
  return {
@@ -4003,6 +4040,15 @@ function createFFIDClient(config) {
4003
4040
  try {
4004
4041
  raw = await response.json();
4005
4042
  } catch (parseError) {
4043
+ if (fetchOptions.signal?.aborted) {
4044
+ logger.error("Response body aborted:", parseError);
4045
+ return {
4046
+ error: {
4047
+ code: FFID_ERROR_CODES.NETWORK_ERROR,
4048
+ message: "\u30EC\u30B9\u30DD\u30F3\u30B9\u306E\u53D7\u4FE1\u304C\u4E2D\u65AD\u3055\u308C\u307E\u3057\u305F"
4049
+ }
4050
+ };
4051
+ }
4006
4052
  logger.error("Parse error:", parseError, "Status:", response.status);
4007
4053
  return {
4008
4054
  error: {
@@ -4548,6 +4594,19 @@ function generateServerState() {
4548
4594
  globalThis.crypto.getRandomValues(bytes);
4549
4595
  return Array.from(bytes, (b) => b.toString(HEX_RADIX2).padStart(2, "0")).join("");
4550
4596
  }
4597
+ var STORED_STATE_SEPARATOR = ".";
4598
+ function packStoredLoginHandle(handle) {
4599
+ return `${handle.state}${STORED_STATE_SEPARATOR}${handle.codeVerifier}`;
4600
+ }
4601
+ function unpackStoredLoginHandle(stored) {
4602
+ if (!stored) return null;
4603
+ const sep = stored.indexOf(STORED_STATE_SEPARATOR);
4604
+ if (sep <= 0) return null;
4605
+ const state = stored.slice(0, sep);
4606
+ const codeVerifier = stored.slice(sep + STORED_STATE_SEPARATOR.length);
4607
+ if (!codeVerifier) return null;
4608
+ return { state, codeVerifier };
4609
+ }
4551
4610
 
4552
4611
  // src/server/auth/server-oauth-token.ts
4553
4612
  var OAUTH_TOKEN_ENDPOINT2 = "/api/v1/oauth/token";
@@ -4609,7 +4668,7 @@ async function postToken(deps, body, fallbackErrorCode) {
4609
4668
  }
4610
4669
  return { tokens: toTokens(validation.tokens) };
4611
4670
  }
4612
- function exchangeAuthorizationCodeServer(deps, code) {
4671
+ function exchangeAuthorizationCodeServer(deps, code, codeVerifier) {
4613
4672
  return postToken(
4614
4673
  deps,
4615
4674
  {
@@ -4617,7 +4676,8 @@ function exchangeAuthorizationCodeServer(deps, code) {
4617
4676
  code,
4618
4677
  client_id: deps.clientId,
4619
4678
  client_secret: deps.clientSecret,
4620
- redirect_uri: deps.redirectUri
4679
+ redirect_uri: deps.redirectUri,
4680
+ code_verifier: codeVerifier
4621
4681
  },
4622
4682
  FFID_ERROR_CODES.TOKEN_EXCHANGE_ERROR
4623
4683
  );
@@ -4638,6 +4698,7 @@ function refreshTokensServer(deps, refreshToken) {
4638
4698
  // src/server/auth/server-auth-client.ts
4639
4699
  var OAUTH_AUTHORIZE_ENDPOINT2 = "/api/v1/oauth/authorize";
4640
4700
  var SCREEN_HINT_SIGNUP2 = "signup";
4701
+ var CODE_CHALLENGE_METHOD_S256 = "S256";
4641
4702
  function createServerAuthClient(config) {
4642
4703
  if (!config.serviceCode?.trim()) {
4643
4704
  throw new Error("FFID Server Auth: serviceCode \u304C\u672A\u8A2D\u5B9A\u3067\u3059");
@@ -4662,20 +4723,29 @@ function createServerAuthClient(config) {
4662
4723
  redirectUri: config.redirectUri,
4663
4724
  timeout: config.timeout
4664
4725
  };
4665
- function buildAuthorizeUrl(opts) {
4726
+ async function buildAuthorizeUrl(opts) {
4666
4727
  const state = generateServerState();
4728
+ const codeVerifier = generateCodeVerifier();
4729
+ const codeChallenge = await generateCodeChallenge(codeVerifier);
4667
4730
  const params = new URLSearchParams({
4668
4731
  response_type: "code",
4669
4732
  client_id: clientId,
4670
4733
  scope: config.scope,
4671
4734
  redirect_uri: config.redirectUri,
4672
- state
4735
+ state,
4736
+ code_challenge: codeChallenge,
4737
+ code_challenge_method: CODE_CHALLENGE_METHOD_S256
4673
4738
  });
4674
4739
  const organizationId = opts?.organizationId?.trim();
4675
4740
  if (organizationId) params.set("organization_id", organizationId);
4676
4741
  if (opts?.screenHint === SCREEN_HINT_SIGNUP2) params.set("screen_hint", SCREEN_HINT_SIGNUP2);
4677
4742
  if (opts?.prompt) params.set("prompt", opts.prompt);
4678
- return { url: `${apiBaseUrl}${OAUTH_AUTHORIZE_ENDPOINT2}?${params.toString()}`, state };
4743
+ return {
4744
+ url: `${apiBaseUrl}${OAUTH_AUTHORIZE_ENDPOINT2}?${params.toString()}`,
4745
+ // Opaque cookie value: state + verifier. Only `state` and the challenge
4746
+ // reach the URL; the verifier stays in the caller's httpOnly cookie.
4747
+ state: packStoredLoginHandle({ state, codeVerifier })
4748
+ };
4679
4749
  }
4680
4750
  async function handleCallback(input) {
4681
4751
  let url;
@@ -4689,12 +4759,15 @@ function createServerAuthClient(config) {
4689
4759
  }
4690
4760
  };
4691
4761
  }
4762
+ const stored = unpackStoredLoginHandle(input.storedState);
4692
4763
  const returnedState = url.searchParams.get("state") ?? void 0;
4693
- if (!input.storedState || !returnedState || input.storedState !== returnedState) {
4764
+ if (!stored || !returnedState || stored.state !== returnedState) {
4694
4765
  return {
4695
4766
  error: {
4696
4767
  code: FFID_ERROR_CODES.STATE_MISMATCH_ERROR,
4697
- 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"
4768
+ // Not "CSRF suspected": a state-only cookie written before 12.0.0 also
4769
+ // lands here, once per in-flight login across the upgrade (#6611).
4770
+ message: "OAuth state \u304C\u4E00\u81F4\u3057\u306A\u3044\u304B\u3001\u30ED\u30B0\u30A4\u30F3\u306E\u958B\u59CB\u304B\u3089\u6642\u9593\u304C\u7D4C\u3063\u3066\u3044\u307E\u3059\u3002\u3082\u3046\u4E00\u5EA6\u30ED\u30B0\u30A4\u30F3\u3057\u3066\u304F\u3060\u3055\u3044"
4698
4771
  }
4699
4772
  };
4700
4773
  }
@@ -4711,7 +4784,7 @@ function createServerAuthClient(config) {
4711
4784
  }
4712
4785
  };
4713
4786
  }
4714
- return exchangeAuthorizationCodeServer(deps, code);
4787
+ return exchangeAuthorizationCodeServer(deps, code, stored.codeVerifier);
4715
4788
  }
4716
4789
  function refresh(refreshToken) {
4717
4790
  return refreshTokensServer(deps, refreshToken);
@@ -1,4 +1,4 @@
1
- import { r as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-qcfCWLfs.cjs';
1
+ import { r as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-DW8_m1_M.cjs';
2
2
  import '../../types-Cjb9J0rL.cjs';
3
3
 
4
4
  /**
@@ -1,4 +1,4 @@
1
- import { r as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-DUbQLYTN.js';
1
+ import { r as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-ByfZA9sJ.js';
2
2
  import '../../types-Cjb9J0rL.js';
3
3
 
4
4
  /**
@@ -115,7 +115,17 @@ interface FFIDCreditsPackPurchasedPayload extends FFIDCreditsEventBase {
115
115
  */
116
116
 
117
117
  /** All supported webhook event types */
118
- type FFIDWebhookEventType = 'subscription.created' | 'subscription.reactivated' | 'subscription.updated' | 'subscription.canceled' | 'subscription.downgrade_scheduled' | 'subscription.downgrade_applied' | 'subscription.downgrade_canceled' | 'subscription.trial_ending' | 'subscription.payment_failed' | 'user.created' | 'user.updated' | 'user.deleted' | 'user.deletion_requested' | 'organization.created' | 'organization.updated' | 'organization.member.added' | 'organization.member.removed' | 'organization.member.role_changed' | 'legal.document.updated' | 'legal.agreement.required' | 'system.maintenance.scheduled' | 'system.maintenance.started' | 'system.maintenance.completed' | 'announcement.published' | 'credits.granted' | 'credits.low' | 'credits.exhausted' | 'credits.pack_purchased' | 'test.ping';
118
+ type FFIDWebhookEventType = 'subscription.created' | 'subscription.reactivated' | 'subscription.updated' | 'subscription.seats.changed' | 'subscription.canceled' | 'subscription.downgrade_scheduled' | 'subscription.downgrade_applied' | 'subscription.downgrade_canceled' | 'subscription.trial_ending' | 'subscription.payment_failed' | 'user.created' | 'user.updated' | 'user.deleted' | 'user.deletion_requested' | 'organization.created' | 'organization.updated' | 'organization.member.added' | 'organization.member.removed' | 'organization.member.role_changed' | 'legal.document.updated' | 'legal.agreement.required' | 'system.maintenance.scheduled' | 'system.maintenance.started' | 'system.maintenance.completed' | 'announcement.published' | 'credits.granted' | 'credits.low' | 'credits.exhausted' | 'credits.pack_purchased' | 'test.ping';
119
+ /**
120
+ * Seat-roster reconciliation hint. Fetch the current roster from FFID; delivery
121
+ * can be delayed, duplicated or reordered. This event grants no access by itself.
122
+ */
123
+ interface FFIDSubscriptionSeatsChangedPayload {
124
+ subscriptionId: string;
125
+ organizationId: string;
126
+ /** Compare with the receiver's own service before reading/reconciling its roster. */
127
+ serviceCode?: string;
128
+ }
119
129
  interface FFIDSubscriptionCreatedPayload {
120
130
  subscriptionId: string;
121
131
  organizationId?: string;
@@ -500,6 +510,7 @@ interface FFIDWebhookEventMap {
500
510
  'subscription.created': FFIDSubscriptionCreatedPayload;
501
511
  'subscription.reactivated': FFIDSubscriptionReactivatedPayload;
502
512
  'subscription.updated': FFIDSubscriptionUpdatedPayload;
513
+ 'subscription.seats.changed': FFIDSubscriptionSeatsChangedPayload;
503
514
  'subscription.canceled': FFIDSubscriptionCanceledPayload;
504
515
  'subscription.downgrade_scheduled': FFIDSubscriptionDowngradeScheduledPayload;
505
516
  'subscription.downgrade_applied': FFIDSubscriptionDowngradeAppliedPayload;
@@ -650,4 +661,4 @@ declare function createFFIDWebhookHandler(config: FFIDWebhookHandlerConfig): {
650
661
  /** Type of the FFID Webhook handler */
651
662
  type FFIDWebhookHandler = ReturnType<typeof createFFIDWebhookHandler>;
652
663
 
653
- export { DEFAULT_TOLERANCE_SECONDS, type FFIDAnnouncementPublishedPayload, type FFIDCreditsExhaustedPayload, type FFIDCreditsGrantedPayload, type FFIDCreditsLowPayload, type FFIDCreditsPackPurchasedPayload, type FFIDLegalAgreementRequiredPayload, type FFIDLegalDocumentUpdatedPayload, type FFIDOrganizationCreatedPayload, type FFIDOrganizationMemberAddedPayload, type FFIDOrganizationMemberRemovedPayload, type FFIDOrganizationMemberRoleChangedPayload, type FFIDOrganizationUpdatedPayload, type FFIDSubscriptionCanceledPayload, type FFIDSubscriptionCreatedPayload, type FFIDSubscriptionDowngradeAppliedPayload, type FFIDSubscriptionDowngradeCanceledPayload, type FFIDSubscriptionDowngradeScheduledPayload, type FFIDSubscriptionPaymentFailedPayload, type FFIDSubscriptionReactivatedPayload, type FFIDSubscriptionTrialEndingPayload, type FFIDSubscriptionUpdatedPayload, type FFIDSystemMaintenancePayload, type FFIDTestPingPayload, type FFIDUserCreatedPayload, type FFIDUserDeletedPayload, type FFIDUserDeletionRequestedPayload, type FFIDUserUpdatedPayload, FFIDWebhookError, type FFIDWebhookEvent, type FFIDWebhookEventHandler, type FFIDWebhookEventMap, type FFIDWebhookEventType, type FFIDWebhookHandler, type FFIDWebhookHandlerConfig, type FFIDWebhookLogger, FFIDWebhookPayloadError, FFIDWebhookSignatureError, FFIDWebhookTimestampError, FFID_WEBHOOK_EVENT_ID_HEADER, FFID_WEBHOOK_SIGNATURE_HEADER, FFID_WEBHOOK_SIGNATURE_VERSION, FFID_WEBHOOK_TIMESTAMP_HEADER, computeSignature, createFFIDWebhookHandler, parseSignatureHeader, verifyWebhookSignature };
664
+ export { DEFAULT_TOLERANCE_SECONDS, type FFIDAnnouncementPublishedPayload, type FFIDCreditsExhaustedPayload, type FFIDCreditsGrantedPayload, type FFIDCreditsLowPayload, type FFIDCreditsPackPurchasedPayload, type FFIDLegalAgreementRequiredPayload, type FFIDLegalDocumentUpdatedPayload, type FFIDOrganizationCreatedPayload, type FFIDOrganizationMemberAddedPayload, type FFIDOrganizationMemberRemovedPayload, type FFIDOrganizationMemberRoleChangedPayload, type FFIDOrganizationUpdatedPayload, type FFIDSubscriptionCanceledPayload, type FFIDSubscriptionCreatedPayload, type FFIDSubscriptionDowngradeAppliedPayload, type FFIDSubscriptionDowngradeCanceledPayload, type FFIDSubscriptionDowngradeScheduledPayload, type FFIDSubscriptionPaymentFailedPayload, type FFIDSubscriptionReactivatedPayload, type FFIDSubscriptionSeatsChangedPayload, type FFIDSubscriptionTrialEndingPayload, type FFIDSubscriptionUpdatedPayload, type FFIDSystemMaintenancePayload, type FFIDTestPingPayload, type FFIDUserCreatedPayload, type FFIDUserDeletedPayload, type FFIDUserDeletionRequestedPayload, type FFIDUserUpdatedPayload, FFIDWebhookError, type FFIDWebhookEvent, type FFIDWebhookEventHandler, type FFIDWebhookEventMap, type FFIDWebhookEventType, type FFIDWebhookHandler, type FFIDWebhookHandlerConfig, type FFIDWebhookLogger, FFIDWebhookPayloadError, FFIDWebhookSignatureError, FFIDWebhookTimestampError, FFID_WEBHOOK_EVENT_ID_HEADER, FFID_WEBHOOK_SIGNATURE_HEADER, FFID_WEBHOOK_SIGNATURE_VERSION, FFID_WEBHOOK_TIMESTAMP_HEADER, computeSignature, createFFIDWebhookHandler, parseSignatureHeader, verifyWebhookSignature };
@@ -115,7 +115,17 @@ interface FFIDCreditsPackPurchasedPayload extends FFIDCreditsEventBase {
115
115
  */
116
116
 
117
117
  /** All supported webhook event types */
118
- type FFIDWebhookEventType = 'subscription.created' | 'subscription.reactivated' | 'subscription.updated' | 'subscription.canceled' | 'subscription.downgrade_scheduled' | 'subscription.downgrade_applied' | 'subscription.downgrade_canceled' | 'subscription.trial_ending' | 'subscription.payment_failed' | 'user.created' | 'user.updated' | 'user.deleted' | 'user.deletion_requested' | 'organization.created' | 'organization.updated' | 'organization.member.added' | 'organization.member.removed' | 'organization.member.role_changed' | 'legal.document.updated' | 'legal.agreement.required' | 'system.maintenance.scheduled' | 'system.maintenance.started' | 'system.maintenance.completed' | 'announcement.published' | 'credits.granted' | 'credits.low' | 'credits.exhausted' | 'credits.pack_purchased' | 'test.ping';
118
+ type FFIDWebhookEventType = 'subscription.created' | 'subscription.reactivated' | 'subscription.updated' | 'subscription.seats.changed' | 'subscription.canceled' | 'subscription.downgrade_scheduled' | 'subscription.downgrade_applied' | 'subscription.downgrade_canceled' | 'subscription.trial_ending' | 'subscription.payment_failed' | 'user.created' | 'user.updated' | 'user.deleted' | 'user.deletion_requested' | 'organization.created' | 'organization.updated' | 'organization.member.added' | 'organization.member.removed' | 'organization.member.role_changed' | 'legal.document.updated' | 'legal.agreement.required' | 'system.maintenance.scheduled' | 'system.maintenance.started' | 'system.maintenance.completed' | 'announcement.published' | 'credits.granted' | 'credits.low' | 'credits.exhausted' | 'credits.pack_purchased' | 'test.ping';
119
+ /**
120
+ * Seat-roster reconciliation hint. Fetch the current roster from FFID; delivery
121
+ * can be delayed, duplicated or reordered. This event grants no access by itself.
122
+ */
123
+ interface FFIDSubscriptionSeatsChangedPayload {
124
+ subscriptionId: string;
125
+ organizationId: string;
126
+ /** Compare with the receiver's own service before reading/reconciling its roster. */
127
+ serviceCode?: string;
128
+ }
119
129
  interface FFIDSubscriptionCreatedPayload {
120
130
  subscriptionId: string;
121
131
  organizationId?: string;
@@ -500,6 +510,7 @@ interface FFIDWebhookEventMap {
500
510
  'subscription.created': FFIDSubscriptionCreatedPayload;
501
511
  'subscription.reactivated': FFIDSubscriptionReactivatedPayload;
502
512
  'subscription.updated': FFIDSubscriptionUpdatedPayload;
513
+ 'subscription.seats.changed': FFIDSubscriptionSeatsChangedPayload;
503
514
  'subscription.canceled': FFIDSubscriptionCanceledPayload;
504
515
  'subscription.downgrade_scheduled': FFIDSubscriptionDowngradeScheduledPayload;
505
516
  'subscription.downgrade_applied': FFIDSubscriptionDowngradeAppliedPayload;
@@ -650,4 +661,4 @@ declare function createFFIDWebhookHandler(config: FFIDWebhookHandlerConfig): {
650
661
  /** Type of the FFID Webhook handler */
651
662
  type FFIDWebhookHandler = ReturnType<typeof createFFIDWebhookHandler>;
652
663
 
653
- export { DEFAULT_TOLERANCE_SECONDS, type FFIDAnnouncementPublishedPayload, type FFIDCreditsExhaustedPayload, type FFIDCreditsGrantedPayload, type FFIDCreditsLowPayload, type FFIDCreditsPackPurchasedPayload, type FFIDLegalAgreementRequiredPayload, type FFIDLegalDocumentUpdatedPayload, type FFIDOrganizationCreatedPayload, type FFIDOrganizationMemberAddedPayload, type FFIDOrganizationMemberRemovedPayload, type FFIDOrganizationMemberRoleChangedPayload, type FFIDOrganizationUpdatedPayload, type FFIDSubscriptionCanceledPayload, type FFIDSubscriptionCreatedPayload, type FFIDSubscriptionDowngradeAppliedPayload, type FFIDSubscriptionDowngradeCanceledPayload, type FFIDSubscriptionDowngradeScheduledPayload, type FFIDSubscriptionPaymentFailedPayload, type FFIDSubscriptionReactivatedPayload, type FFIDSubscriptionTrialEndingPayload, type FFIDSubscriptionUpdatedPayload, type FFIDSystemMaintenancePayload, type FFIDTestPingPayload, type FFIDUserCreatedPayload, type FFIDUserDeletedPayload, type FFIDUserDeletionRequestedPayload, type FFIDUserUpdatedPayload, FFIDWebhookError, type FFIDWebhookEvent, type FFIDWebhookEventHandler, type FFIDWebhookEventMap, type FFIDWebhookEventType, type FFIDWebhookHandler, type FFIDWebhookHandlerConfig, type FFIDWebhookLogger, FFIDWebhookPayloadError, FFIDWebhookSignatureError, FFIDWebhookTimestampError, FFID_WEBHOOK_EVENT_ID_HEADER, FFID_WEBHOOK_SIGNATURE_HEADER, FFID_WEBHOOK_SIGNATURE_VERSION, FFID_WEBHOOK_TIMESTAMP_HEADER, computeSignature, createFFIDWebhookHandler, parseSignatureHeader, verifyWebhookSignature };
664
+ export { DEFAULT_TOLERANCE_SECONDS, type FFIDAnnouncementPublishedPayload, type FFIDCreditsExhaustedPayload, type FFIDCreditsGrantedPayload, type FFIDCreditsLowPayload, type FFIDCreditsPackPurchasedPayload, type FFIDLegalAgreementRequiredPayload, type FFIDLegalDocumentUpdatedPayload, type FFIDOrganizationCreatedPayload, type FFIDOrganizationMemberAddedPayload, type FFIDOrganizationMemberRemovedPayload, type FFIDOrganizationMemberRoleChangedPayload, type FFIDOrganizationUpdatedPayload, type FFIDSubscriptionCanceledPayload, type FFIDSubscriptionCreatedPayload, type FFIDSubscriptionDowngradeAppliedPayload, type FFIDSubscriptionDowngradeCanceledPayload, type FFIDSubscriptionDowngradeScheduledPayload, type FFIDSubscriptionPaymentFailedPayload, type FFIDSubscriptionReactivatedPayload, type FFIDSubscriptionSeatsChangedPayload, type FFIDSubscriptionTrialEndingPayload, type FFIDSubscriptionUpdatedPayload, type FFIDSystemMaintenancePayload, type FFIDTestPingPayload, type FFIDUserCreatedPayload, type FFIDUserDeletedPayload, type FFIDUserDeletionRequestedPayload, type FFIDUserUpdatedPayload, FFIDWebhookError, type FFIDWebhookEvent, type FFIDWebhookEventHandler, type FFIDWebhookEventMap, type FFIDWebhookEventType, type FFIDWebhookHandler, type FFIDWebhookHandlerConfig, type FFIDWebhookLogger, FFIDWebhookPayloadError, FFIDWebhookSignatureError, FFIDWebhookTimestampError, FFID_WEBHOOK_EVENT_ID_HEADER, FFID_WEBHOOK_SIGNATURE_HEADER, FFID_WEBHOOK_SIGNATURE_VERSION, FFID_WEBHOOK_TIMESTAMP_HEADER, computeSignature, createFFIDWebhookHandler, parseSignatureHeader, verifyWebhookSignature };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelflow/ffid-sdk",
3
- "version": "10.1.0",
3
+ "version": "12.0.0",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",