@feelflow/ffid-sdk 7.2.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -5
- package/dist/{chunk-SOZ2B2ZL.cjs → chunk-CPXTIRB6.cjs} +204 -12
- package/dist/{chunk-E2AJAVX6.js → chunk-P5A6C5SK.js} +195 -13
- package/dist/components/index.cjs +8 -8
- package/dist/components/index.d.cts +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.js +1 -1
- package/dist/{ffid-client-BFgoVPOZ.d.cts → ffid-client-6aLs9Fqc.d.cts} +116 -29
- package/dist/{ffid-client-QNEFA3mv.d.ts → ffid-client-B0cORHac.d.ts} +116 -29
- package/dist/{index-BMKhKhzF.d.cts → index-BG7g99pK.d.cts} +1 -0
- package/dist/{index-BMKhKhzF.d.ts → index-BG7g99pK.d.ts} +1 -0
- package/dist/index.cjs +104 -64
- package/dist/index.d.cts +389 -32
- package/dist/index.d.ts +389 -32
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +128 -10
- package/dist/server/index.d.cts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +128 -10
- package/dist/server/test/index.d.cts +1 -1
- package/dist/server/test/index.d.ts +1 -1
- package/dist/webhooks/index.d.cts +125 -6
- package/dist/webhooks/index.d.ts +125 -6
- package/package.json +1 -1
|
@@ -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;
|
|
@@ -55,6 +55,14 @@ interface FFIDSubscriptionCreatedPayload {
|
|
|
55
55
|
status?: string;
|
|
56
56
|
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
57
57
|
gracePeriodEndsAt?: string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
60
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
61
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
62
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
63
|
+
* "not addressed to this service".
|
|
64
|
+
*/
|
|
65
|
+
serviceCode?: string;
|
|
58
66
|
}
|
|
59
67
|
interface FFIDSubscriptionUpdatedPayload {
|
|
60
68
|
subscriptionId: string;
|
|
@@ -64,7 +72,61 @@ interface FFIDSubscriptionUpdatedPayload {
|
|
|
64
72
|
status?: string;
|
|
65
73
|
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
66
74
|
gracePeriodEndsAt?: string | null;
|
|
75
|
+
/**
|
|
76
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
77
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
78
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
79
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
80
|
+
* "not addressed to this service".
|
|
81
|
+
*/
|
|
82
|
+
serviceCode?: string;
|
|
67
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* `subscription.reactivated` (8.0.0): a cancellation reserved until the period end was
|
|
86
|
+
* withdrawn in the FFID portal, so the subscription continues. It pairs with the
|
|
87
|
+
* reservation-time `subscription.canceled` (`source: 'user_initiated'`,
|
|
88
|
+
* `reactivatable: true`). Sent only for contracts billed through Stripe.
|
|
89
|
+
*/
|
|
90
|
+
interface FFIDSubscriptionReactivatedPayload {
|
|
91
|
+
subscriptionId: string;
|
|
92
|
+
organizationId?: string;
|
|
93
|
+
/** Plan code */
|
|
94
|
+
plan?: string;
|
|
95
|
+
status?: string;
|
|
96
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
97
|
+
gracePeriodEndsAt?: string | null;
|
|
98
|
+
stripeSubscriptionId: string;
|
|
99
|
+
stripeCustomerId: string;
|
|
100
|
+
/**
|
|
101
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
102
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
103
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
104
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
105
|
+
* "not addressed to this service".
|
|
106
|
+
*/
|
|
107
|
+
serviceCode?: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* `subscription.canceled`.
|
|
111
|
+
*
|
|
112
|
+
* A contract billed through Stripe is canceled in two steps (FFID #6327), so **two events
|
|
113
|
+
* arrive per cancellation**:
|
|
114
|
+
*
|
|
115
|
+
* 1. At the reservation — `source: 'user_initiated'`, `reactivatable: true`, `cancelAt` /
|
|
116
|
+
* `expiredAt` = the period end, no `effectiveStatus`. **Access continues until `cancelAt`**;
|
|
117
|
+
* do not revoke it here. The reservation may still be withdrawn
|
|
118
|
+
* (`subscription.reactivated`).
|
|
119
|
+
* 2. At the period end — `source: 'stripe_confirmed'`, `effectiveStatus: 'canceled'`. Revoke
|
|
120
|
+
* access on this one.
|
|
121
|
+
*
|
|
122
|
+
* **Rule for consumers:** only an event with `source === 'user_initiated'` **and** a
|
|
123
|
+
* `cancelAt` is a reservation (keep access until `cancelAt`). Every other
|
|
124
|
+
* `subscription.canceled` ends access: the final `stripe_confirmed`, an immediate
|
|
125
|
+
* cancellation (`user_initiated` without `cancelAt` — a contract that cannot be reserved,
|
|
126
|
+
* e.g. no Stripe subscription or no period end yet; `expiredAt` is the cancellation time),
|
|
127
|
+
* and `payment_failure_auto_cancel` (automatic cancellation after unpaid invoices).
|
|
128
|
+
* Do not key the decision on `effectiveStatus`: it is set only on Stripe's deletion notice.
|
|
129
|
+
*/
|
|
68
130
|
interface FFIDSubscriptionCanceledPayload {
|
|
69
131
|
/** FFID subscription UUID. */
|
|
70
132
|
subscriptionId: string;
|
|
@@ -80,23 +142,39 @@ interface FFIDSubscriptionCanceledPayload {
|
|
|
80
142
|
*/
|
|
81
143
|
stripeSubscriptionId: string | null;
|
|
82
144
|
reason?: string;
|
|
145
|
+
/** When a reserved cancellation takes effect (the period end) */
|
|
83
146
|
cancelAt?: string;
|
|
84
147
|
/**
|
|
85
148
|
* Origin of the cancellation. Always emitted by the FFID server — required
|
|
86
|
-
* by the wire shape in `SubscriptionCanceledPayload`.
|
|
149
|
+
* by the wire shape in `SubscriptionCanceledPayload`. Distinguishes the reservation
|
|
150
|
+
* (`user_initiated`) from the final event (`stripe_confirmed`); see the interface doc.
|
|
87
151
|
*/
|
|
88
152
|
source: 'user_initiated' | 'stripe_confirmed' | 'payment_failure_auto_cancel';
|
|
89
153
|
/** Whether this cancellation can be resumed via resubscribe flow. */
|
|
90
154
|
reactivatable?: boolean;
|
|
91
155
|
/**
|
|
92
|
-
* ISO timestamp at which access was
|
|
93
|
-
* when Stripe runs out the paid period
|
|
156
|
+
* ISO timestamp at which access is (or was) lost. On the reservation event this is the
|
|
157
|
+
* future period end. May differ from `cancelAt` when Stripe runs out the paid period
|
|
158
|
+
* before emitting the deletion event.
|
|
94
159
|
*/
|
|
95
160
|
expiredAt?: string;
|
|
96
|
-
/**
|
|
161
|
+
/**
|
|
162
|
+
* `canceled` only on Stripe's deletion notice (e.g. the final `stripe_confirmed`). Absent on
|
|
163
|
+
* the reservation event, on immediate cancellations and on the cron's
|
|
164
|
+
* `payment_failure_auto_cancel` — so its absence does not mean "still usable"; decide by
|
|
165
|
+
* `source` + `cancelAt` (see the interface doc).
|
|
166
|
+
*/
|
|
97
167
|
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
98
168
|
/** Always null for cancellation events because no grace window remains. */
|
|
99
169
|
gracePeriodEndsAt?: string | null;
|
|
170
|
+
/**
|
|
171
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
172
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
173
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
174
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
175
|
+
* "not addressed to this service".
|
|
176
|
+
*/
|
|
177
|
+
serviceCode?: string;
|
|
100
178
|
}
|
|
101
179
|
interface FFIDSubscriptionDowngradeScheduledPayload {
|
|
102
180
|
/** FFID subscription UUID. */
|
|
@@ -113,6 +191,14 @@ interface FFIDSubscriptionDowngradeScheduledPayload {
|
|
|
113
191
|
scheduledAt: string;
|
|
114
192
|
/** ISO timestamp when the scheduled downgrade should take effect. */
|
|
115
193
|
effectiveAt: string;
|
|
194
|
+
/**
|
|
195
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
196
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
197
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
198
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
199
|
+
* "not addressed to this service".
|
|
200
|
+
*/
|
|
201
|
+
serviceCode?: string;
|
|
116
202
|
}
|
|
117
203
|
interface FFIDSubscriptionDowngradeAppliedPayload {
|
|
118
204
|
/** FFID subscription UUID. */
|
|
@@ -127,6 +213,14 @@ interface FFIDSubscriptionDowngradeAppliedPayload {
|
|
|
127
213
|
billingInterval: string;
|
|
128
214
|
/** ISO timestamp when FFID applied the pending downgrade. */
|
|
129
215
|
appliedAt: string;
|
|
216
|
+
/**
|
|
217
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
218
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
219
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
220
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
221
|
+
* "not addressed to this service".
|
|
222
|
+
*/
|
|
223
|
+
serviceCode?: string;
|
|
130
224
|
}
|
|
131
225
|
interface FFIDSubscriptionDowngradeCanceledPayload {
|
|
132
226
|
/** FFID subscription UUID. */
|
|
@@ -139,11 +233,27 @@ interface FFIDSubscriptionDowngradeCanceledPayload {
|
|
|
139
233
|
currentPlanId: string;
|
|
140
234
|
/** ISO timestamp when the pending downgrade was canceled. */
|
|
141
235
|
canceledAt: string;
|
|
236
|
+
/**
|
|
237
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
238
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
239
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
240
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
241
|
+
* "not addressed to this service".
|
|
242
|
+
*/
|
|
243
|
+
serviceCode?: string;
|
|
142
244
|
}
|
|
143
245
|
interface FFIDSubscriptionTrialEndingPayload {
|
|
144
246
|
subscriptionId: string;
|
|
145
247
|
organizationId?: string;
|
|
146
248
|
trialEndDate: string;
|
|
249
|
+
/**
|
|
250
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
251
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
252
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
253
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
254
|
+
* "not addressed to this service".
|
|
255
|
+
*/
|
|
256
|
+
serviceCode?: string;
|
|
147
257
|
}
|
|
148
258
|
interface FFIDSubscriptionPaymentFailedPayload {
|
|
149
259
|
/**
|
|
@@ -201,6 +311,14 @@ interface FFIDSubscriptionPaymentFailedPayload {
|
|
|
201
311
|
* "backend has no mapping yet" from "payload shape regression".
|
|
202
312
|
*/
|
|
203
313
|
correlationUnavailable?: boolean;
|
|
314
|
+
/**
|
|
315
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
316
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
317
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
318
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
319
|
+
* "not addressed to this service".
|
|
320
|
+
*/
|
|
321
|
+
serviceCode?: string;
|
|
204
322
|
}
|
|
205
323
|
interface FFIDUserCreatedPayload {
|
|
206
324
|
userId: string;
|
|
@@ -279,6 +397,7 @@ interface FFIDTestPingPayload {
|
|
|
279
397
|
/** Maps event type strings to their typed payloads */
|
|
280
398
|
interface FFIDWebhookEventMap {
|
|
281
399
|
'subscription.created': FFIDSubscriptionCreatedPayload;
|
|
400
|
+
'subscription.reactivated': FFIDSubscriptionReactivatedPayload;
|
|
282
401
|
'subscription.updated': FFIDSubscriptionUpdatedPayload;
|
|
283
402
|
'subscription.canceled': FFIDSubscriptionCanceledPayload;
|
|
284
403
|
'subscription.downgrade_scheduled': FFIDSubscriptionDowngradeScheduledPayload;
|
|
@@ -426,4 +545,4 @@ declare function createFFIDWebhookHandler(config: FFIDWebhookHandlerConfig): {
|
|
|
426
545
|
/** Type of the FFID Webhook handler */
|
|
427
546
|
type FFIDWebhookHandler = ReturnType<typeof createFFIDWebhookHandler>;
|
|
428
547
|
|
|
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 };
|
|
548
|
+
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/dist/webhooks/index.d.ts
CHANGED
|
@@ -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;
|
|
@@ -55,6 +55,14 @@ interface FFIDSubscriptionCreatedPayload {
|
|
|
55
55
|
status?: string;
|
|
56
56
|
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
57
57
|
gracePeriodEndsAt?: string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
60
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
61
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
62
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
63
|
+
* "not addressed to this service".
|
|
64
|
+
*/
|
|
65
|
+
serviceCode?: string;
|
|
58
66
|
}
|
|
59
67
|
interface FFIDSubscriptionUpdatedPayload {
|
|
60
68
|
subscriptionId: string;
|
|
@@ -64,7 +72,61 @@ interface FFIDSubscriptionUpdatedPayload {
|
|
|
64
72
|
status?: string;
|
|
65
73
|
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
66
74
|
gracePeriodEndsAt?: string | null;
|
|
75
|
+
/**
|
|
76
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
77
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
78
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
79
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
80
|
+
* "not addressed to this service".
|
|
81
|
+
*/
|
|
82
|
+
serviceCode?: string;
|
|
67
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* `subscription.reactivated` (8.0.0): a cancellation reserved until the period end was
|
|
86
|
+
* withdrawn in the FFID portal, so the subscription continues. It pairs with the
|
|
87
|
+
* reservation-time `subscription.canceled` (`source: 'user_initiated'`,
|
|
88
|
+
* `reactivatable: true`). Sent only for contracts billed through Stripe.
|
|
89
|
+
*/
|
|
90
|
+
interface FFIDSubscriptionReactivatedPayload {
|
|
91
|
+
subscriptionId: string;
|
|
92
|
+
organizationId?: string;
|
|
93
|
+
/** Plan code */
|
|
94
|
+
plan?: string;
|
|
95
|
+
status?: string;
|
|
96
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
97
|
+
gracePeriodEndsAt?: string | null;
|
|
98
|
+
stripeSubscriptionId: string;
|
|
99
|
+
stripeCustomerId: string;
|
|
100
|
+
/**
|
|
101
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
102
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
103
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
104
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
105
|
+
* "not addressed to this service".
|
|
106
|
+
*/
|
|
107
|
+
serviceCode?: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* `subscription.canceled`.
|
|
111
|
+
*
|
|
112
|
+
* A contract billed through Stripe is canceled in two steps (FFID #6327), so **two events
|
|
113
|
+
* arrive per cancellation**:
|
|
114
|
+
*
|
|
115
|
+
* 1. At the reservation — `source: 'user_initiated'`, `reactivatable: true`, `cancelAt` /
|
|
116
|
+
* `expiredAt` = the period end, no `effectiveStatus`. **Access continues until `cancelAt`**;
|
|
117
|
+
* do not revoke it here. The reservation may still be withdrawn
|
|
118
|
+
* (`subscription.reactivated`).
|
|
119
|
+
* 2. At the period end — `source: 'stripe_confirmed'`, `effectiveStatus: 'canceled'`. Revoke
|
|
120
|
+
* access on this one.
|
|
121
|
+
*
|
|
122
|
+
* **Rule for consumers:** only an event with `source === 'user_initiated'` **and** a
|
|
123
|
+
* `cancelAt` is a reservation (keep access until `cancelAt`). Every other
|
|
124
|
+
* `subscription.canceled` ends access: the final `stripe_confirmed`, an immediate
|
|
125
|
+
* cancellation (`user_initiated` without `cancelAt` — a contract that cannot be reserved,
|
|
126
|
+
* e.g. no Stripe subscription or no period end yet; `expiredAt` is the cancellation time),
|
|
127
|
+
* and `payment_failure_auto_cancel` (automatic cancellation after unpaid invoices).
|
|
128
|
+
* Do not key the decision on `effectiveStatus`: it is set only on Stripe's deletion notice.
|
|
129
|
+
*/
|
|
68
130
|
interface FFIDSubscriptionCanceledPayload {
|
|
69
131
|
/** FFID subscription UUID. */
|
|
70
132
|
subscriptionId: string;
|
|
@@ -80,23 +142,39 @@ interface FFIDSubscriptionCanceledPayload {
|
|
|
80
142
|
*/
|
|
81
143
|
stripeSubscriptionId: string | null;
|
|
82
144
|
reason?: string;
|
|
145
|
+
/** When a reserved cancellation takes effect (the period end) */
|
|
83
146
|
cancelAt?: string;
|
|
84
147
|
/**
|
|
85
148
|
* Origin of the cancellation. Always emitted by the FFID server — required
|
|
86
|
-
* by the wire shape in `SubscriptionCanceledPayload`.
|
|
149
|
+
* by the wire shape in `SubscriptionCanceledPayload`. Distinguishes the reservation
|
|
150
|
+
* (`user_initiated`) from the final event (`stripe_confirmed`); see the interface doc.
|
|
87
151
|
*/
|
|
88
152
|
source: 'user_initiated' | 'stripe_confirmed' | 'payment_failure_auto_cancel';
|
|
89
153
|
/** Whether this cancellation can be resumed via resubscribe flow. */
|
|
90
154
|
reactivatable?: boolean;
|
|
91
155
|
/**
|
|
92
|
-
* ISO timestamp at which access was
|
|
93
|
-
* when Stripe runs out the paid period
|
|
156
|
+
* ISO timestamp at which access is (or was) lost. On the reservation event this is the
|
|
157
|
+
* future period end. May differ from `cancelAt` when Stripe runs out the paid period
|
|
158
|
+
* before emitting the deletion event.
|
|
94
159
|
*/
|
|
95
160
|
expiredAt?: string;
|
|
96
|
-
/**
|
|
161
|
+
/**
|
|
162
|
+
* `canceled` only on Stripe's deletion notice (e.g. the final `stripe_confirmed`). Absent on
|
|
163
|
+
* the reservation event, on immediate cancellations and on the cron's
|
|
164
|
+
* `payment_failure_auto_cancel` — so its absence does not mean "still usable"; decide by
|
|
165
|
+
* `source` + `cancelAt` (see the interface doc).
|
|
166
|
+
*/
|
|
97
167
|
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
98
168
|
/** Always null for cancellation events because no grace window remains. */
|
|
99
169
|
gracePeriodEndsAt?: string | null;
|
|
170
|
+
/**
|
|
171
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
172
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
173
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
174
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
175
|
+
* "not addressed to this service".
|
|
176
|
+
*/
|
|
177
|
+
serviceCode?: string;
|
|
100
178
|
}
|
|
101
179
|
interface FFIDSubscriptionDowngradeScheduledPayload {
|
|
102
180
|
/** FFID subscription UUID. */
|
|
@@ -113,6 +191,14 @@ interface FFIDSubscriptionDowngradeScheduledPayload {
|
|
|
113
191
|
scheduledAt: string;
|
|
114
192
|
/** ISO timestamp when the scheduled downgrade should take effect. */
|
|
115
193
|
effectiveAt: string;
|
|
194
|
+
/**
|
|
195
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
196
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
197
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
198
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
199
|
+
* "not addressed to this service".
|
|
200
|
+
*/
|
|
201
|
+
serviceCode?: string;
|
|
116
202
|
}
|
|
117
203
|
interface FFIDSubscriptionDowngradeAppliedPayload {
|
|
118
204
|
/** FFID subscription UUID. */
|
|
@@ -127,6 +213,14 @@ interface FFIDSubscriptionDowngradeAppliedPayload {
|
|
|
127
213
|
billingInterval: string;
|
|
128
214
|
/** ISO timestamp when FFID applied the pending downgrade. */
|
|
129
215
|
appliedAt: string;
|
|
216
|
+
/**
|
|
217
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
218
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
219
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
220
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
221
|
+
* "not addressed to this service".
|
|
222
|
+
*/
|
|
223
|
+
serviceCode?: string;
|
|
130
224
|
}
|
|
131
225
|
interface FFIDSubscriptionDowngradeCanceledPayload {
|
|
132
226
|
/** FFID subscription UUID. */
|
|
@@ -139,11 +233,27 @@ interface FFIDSubscriptionDowngradeCanceledPayload {
|
|
|
139
233
|
currentPlanId: string;
|
|
140
234
|
/** ISO timestamp when the pending downgrade was canceled. */
|
|
141
235
|
canceledAt: string;
|
|
236
|
+
/**
|
|
237
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
238
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
239
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
240
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
241
|
+
* "not addressed to this service".
|
|
242
|
+
*/
|
|
243
|
+
serviceCode?: string;
|
|
142
244
|
}
|
|
143
245
|
interface FFIDSubscriptionTrialEndingPayload {
|
|
144
246
|
subscriptionId: string;
|
|
145
247
|
organizationId?: string;
|
|
146
248
|
trialEndDate: string;
|
|
249
|
+
/**
|
|
250
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
251
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
252
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
253
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
254
|
+
* "not addressed to this service".
|
|
255
|
+
*/
|
|
256
|
+
serviceCode?: string;
|
|
147
257
|
}
|
|
148
258
|
interface FFIDSubscriptionPaymentFailedPayload {
|
|
149
259
|
/**
|
|
@@ -201,6 +311,14 @@ interface FFIDSubscriptionPaymentFailedPayload {
|
|
|
201
311
|
* "backend has no mapping yet" from "payload shape regression".
|
|
202
312
|
*/
|
|
203
313
|
correlationUnavailable?: boolean;
|
|
314
|
+
/**
|
|
315
|
+
* Code of the service the subscription belongs to (e.g. `chatbot-v2`), resolved by FFID when
|
|
316
|
+
* the event is sent. Every `subscription.*` event is broadcast to all endpoints subscribed to
|
|
317
|
+
* that event type, so compare this with your own service code to skip events for other
|
|
318
|
+
* services. Absent only when FFID could not resolve it — do not read absence as
|
|
319
|
+
* "not addressed to this service".
|
|
320
|
+
*/
|
|
321
|
+
serviceCode?: string;
|
|
204
322
|
}
|
|
205
323
|
interface FFIDUserCreatedPayload {
|
|
206
324
|
userId: string;
|
|
@@ -279,6 +397,7 @@ interface FFIDTestPingPayload {
|
|
|
279
397
|
/** Maps event type strings to their typed payloads */
|
|
280
398
|
interface FFIDWebhookEventMap {
|
|
281
399
|
'subscription.created': FFIDSubscriptionCreatedPayload;
|
|
400
|
+
'subscription.reactivated': FFIDSubscriptionReactivatedPayload;
|
|
282
401
|
'subscription.updated': FFIDSubscriptionUpdatedPayload;
|
|
283
402
|
'subscription.canceled': FFIDSubscriptionCanceledPayload;
|
|
284
403
|
'subscription.downgrade_scheduled': FFIDSubscriptionDowngradeScheduledPayload;
|
|
@@ -426,4 +545,4 @@ declare function createFFIDWebhookHandler(config: FFIDWebhookHandlerConfig): {
|
|
|
426
545
|
/** Type of the FFID Webhook handler */
|
|
427
546
|
type FFIDWebhookHandler = ReturnType<typeof createFFIDWebhookHandler>;
|
|
428
547
|
|
|
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 };
|
|
548
|
+
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 };
|