@feelflow/ffid-sdk 7.2.0 → 8.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.
@@ -47,7 +47,7 @@ declare class FFIDWebhookPayloadError extends FFIDWebhookError {
47
47
  */
48
48
 
49
49
  /** All supported webhook event types */
50
- type FFIDWebhookEventType = 'subscription.created' | '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' | 'test.ping';
50
+ 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' | 'test.ping';
51
51
  interface FFIDSubscriptionCreatedPayload {
52
52
  subscriptionId: string;
53
53
  organizationId?: string;
@@ -65,6 +65,46 @@ interface FFIDSubscriptionUpdatedPayload {
65
65
  effectiveStatus?: EffectiveSubscriptionStatus;
66
66
  gracePeriodEndsAt?: string | null;
67
67
  }
68
+ /**
69
+ * `subscription.reactivated` (8.0.0): a cancellation reserved until the period end was
70
+ * withdrawn in the FFID portal, so the subscription continues. It pairs with the
71
+ * reservation-time `subscription.canceled` (`source: 'user_initiated'`,
72
+ * `reactivatable: true`). Sent only for contracts billed through Stripe.
73
+ */
74
+ interface FFIDSubscriptionReactivatedPayload {
75
+ subscriptionId: string;
76
+ organizationId?: string;
77
+ /** Plan code */
78
+ plan?: string;
79
+ status?: string;
80
+ effectiveStatus?: EffectiveSubscriptionStatus;
81
+ gracePeriodEndsAt?: string | null;
82
+ stripeSubscriptionId: string;
83
+ stripeCustomerId: string;
84
+ /** Code of the service the subscription belongs to (resolved by FFID when the event is sent) */
85
+ serviceCode?: string;
86
+ }
87
+ /**
88
+ * `subscription.canceled`.
89
+ *
90
+ * A contract billed through Stripe is canceled in two steps (FFID #6327), so **two events
91
+ * arrive per cancellation**:
92
+ *
93
+ * 1. At the reservation — `source: 'user_initiated'`, `reactivatable: true`, `cancelAt` /
94
+ * `expiredAt` = the period end, no `effectiveStatus`. **Access continues until `cancelAt`**;
95
+ * do not revoke it here. The reservation may still be withdrawn
96
+ * (`subscription.reactivated`).
97
+ * 2. At the period end — `source: 'stripe_confirmed'`, `effectiveStatus: 'canceled'`. Revoke
98
+ * access on this one.
99
+ *
100
+ * **Rule for consumers:** only an event with `source === 'user_initiated'` **and** a
101
+ * `cancelAt` is a reservation (keep access until `cancelAt`). Every other
102
+ * `subscription.canceled` ends access: the final `stripe_confirmed`, an immediate
103
+ * cancellation (`user_initiated` without `cancelAt` — a contract that cannot be reserved,
104
+ * e.g. no Stripe subscription or no period end yet; `expiredAt` is the cancellation time),
105
+ * and `payment_failure_auto_cancel` (automatic cancellation after unpaid invoices).
106
+ * Do not key the decision on `effectiveStatus`: it is set only on Stripe's deletion notice.
107
+ */
68
108
  interface FFIDSubscriptionCanceledPayload {
69
109
  /** FFID subscription UUID. */
70
110
  subscriptionId: string;
@@ -80,20 +120,28 @@ interface FFIDSubscriptionCanceledPayload {
80
120
  */
81
121
  stripeSubscriptionId: string | null;
82
122
  reason?: string;
123
+ /** When a reserved cancellation takes effect (the period end) */
83
124
  cancelAt?: string;
84
125
  /**
85
126
  * Origin of the cancellation. Always emitted by the FFID server — required
86
- * by the wire shape in `SubscriptionCanceledPayload`.
127
+ * by the wire shape in `SubscriptionCanceledPayload`. Distinguishes the reservation
128
+ * (`user_initiated`) from the final event (`stripe_confirmed`); see the interface doc.
87
129
  */
88
130
  source: 'user_initiated' | 'stripe_confirmed' | 'payment_failure_auto_cancel';
89
131
  /** Whether this cancellation can be resumed via resubscribe flow. */
90
132
  reactivatable?: boolean;
91
133
  /**
92
- * ISO timestamp at which access was actually lost. May differ from `cancelAt`
93
- * when Stripe runs out the paid period before emitting the deletion event.
134
+ * ISO timestamp at which access is (or was) lost. On the reservation event this is the
135
+ * future period end. May differ from `cancelAt` when Stripe runs out the paid period
136
+ * before emitting the deletion event.
94
137
  */
95
138
  expiredAt?: string;
96
- /** Cancellation always leaves the canonical access-control status as `canceled`. */
139
+ /**
140
+ * `canceled` only on Stripe's deletion notice (e.g. the final `stripe_confirmed`). Absent on
141
+ * the reservation event, on immediate cancellations and on the cron's
142
+ * `payment_failure_auto_cancel` — so its absence does not mean "still usable"; decide by
143
+ * `source` + `cancelAt` (see the interface doc).
144
+ */
97
145
  effectiveStatus?: EffectiveSubscriptionStatus;
98
146
  /** Always null for cancellation events because no grace window remains. */
99
147
  gracePeriodEndsAt?: string | null;
@@ -279,6 +327,7 @@ interface FFIDTestPingPayload {
279
327
  /** Maps event type strings to their typed payloads */
280
328
  interface FFIDWebhookEventMap {
281
329
  'subscription.created': FFIDSubscriptionCreatedPayload;
330
+ 'subscription.reactivated': FFIDSubscriptionReactivatedPayload;
282
331
  'subscription.updated': FFIDSubscriptionUpdatedPayload;
283
332
  'subscription.canceled': FFIDSubscriptionCanceledPayload;
284
333
  'subscription.downgrade_scheduled': FFIDSubscriptionDowngradeScheduledPayload;
@@ -426,4 +475,4 @@ declare function createFFIDWebhookHandler(config: FFIDWebhookHandlerConfig): {
426
475
  /** Type of the FFID Webhook handler */
427
476
  type FFIDWebhookHandler = ReturnType<typeof createFFIDWebhookHandler>;
428
477
 
429
- export { DEFAULT_TOLERANCE_SECONDS, 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 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 };
478
+ export { DEFAULT_TOLERANCE_SECONDS, 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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@feelflow/ffid-sdk",
3
- "version": "7.2.0",
3
+ "version": "8.0.0",
4
4
  "description": "FeelFlow ID Platform SDK for React/Next.js applications",
5
5
  "keywords": [
6
6
  "feelflow",