@feelflow/ffid-sdk 4.0.0 → 4.2.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 +31 -0
- package/dist/{chunk-XQL4YSTL.cjs → chunk-U4XDH7TI.cjs} +121 -1
- package/dist/{chunk-P35ULJLM.js → chunk-WI645CPU.js} +121 -1
- 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-ZcJhRbD6.d.ts → ffid-client-CKMGqqPi.d.cts} +90 -10
- package/dist/{ffid-client-ZcJhRbD6.d.cts → ffid-client-CUOFknXy.d.ts} +90 -10
- package/dist/{index-Cn8-3hgb.d.cts → index-DXgTH5vK.d.cts} +87 -11
- package/dist/{index-Cn8-3hgb.d.ts → index-DXgTH5vK.d.ts} +87 -11
- package/dist/index.cjs +32 -32
- package/dist/index.d.cts +5 -3
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +121 -1
- package/dist/server/index.d.cts +3 -2
- package/dist/server/index.d.ts +3 -2
- package/dist/server/index.js +121 -1
- package/dist/server/test/index.d.cts +2 -1
- package/dist/server/test/index.d.ts +2 -1
- package/dist/types-5g_Bg6Ey.d.cts +37 -0
- package/dist/types-5g_Bg6Ey.d.ts +37 -0
- package/dist/webhooks/index.d.cts +65 -2
- package/dist/webhooks/index.d.ts +65 -2
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -803,7 +803,7 @@ function createProfileMethods(deps) {
|
|
|
803
803
|
}
|
|
804
804
|
|
|
805
805
|
// src/client/version-check.ts
|
|
806
|
-
var SDK_VERSION = "4.
|
|
806
|
+
var SDK_VERSION = "4.2.0";
|
|
807
807
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
808
808
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
809
809
|
function sdkHeaders() {
|
|
@@ -2180,6 +2180,73 @@ var FFID_ERROR_CODES = {
|
|
|
2180
2180
|
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
|
|
2181
2181
|
};
|
|
2182
2182
|
var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
|
|
2183
|
+
var DEFAULT_ALLOW_GRACE = true;
|
|
2184
|
+
var DEFAULT_SERVICE_ACCESS_FAIL_POLICY = "failClosed";
|
|
2185
|
+
var SERVICE_ACCESS_DENIED_CODE = "SERVICE_ACCESS_DENIED";
|
|
2186
|
+
var ACCESS_GRANTING_EFFECTIVE_STATUSES = ["active", "past_due_grace"];
|
|
2187
|
+
var BLOCKING_EFFECTIVE_STATUSES = [
|
|
2188
|
+
"blocked",
|
|
2189
|
+
"canceled",
|
|
2190
|
+
"expired",
|
|
2191
|
+
"trial_expired"
|
|
2192
|
+
];
|
|
2193
|
+
function resolveServiceAccessDenialReason(params, allowGrace) {
|
|
2194
|
+
if (params.hasAccess) {
|
|
2195
|
+
return null;
|
|
2196
|
+
}
|
|
2197
|
+
if (params.effectiveStatus === null) {
|
|
2198
|
+
return "no_subscription";
|
|
2199
|
+
}
|
|
2200
|
+
if (params.isGrace && !allowGrace) {
|
|
2201
|
+
return "grace_disallowed";
|
|
2202
|
+
}
|
|
2203
|
+
if (params.effectiveStatus === "active" || params.effectiveStatus === "past_due_grace") {
|
|
2204
|
+
return "blocked";
|
|
2205
|
+
}
|
|
2206
|
+
return params.effectiveStatus;
|
|
2207
|
+
}
|
|
2208
|
+
function toServiceAccessDecision(response, allowGrace) {
|
|
2209
|
+
const effectiveStatus = response.effectiveStatus ?? null;
|
|
2210
|
+
const serverHasAccess = response.hasAccess ?? (effectiveStatus !== null && ACCESS_GRANTING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
2211
|
+
const isGrace = response.isGrace ?? effectiveStatus === "past_due_grace";
|
|
2212
|
+
const hasAccess = serverHasAccess && (allowGrace || !isGrace);
|
|
2213
|
+
const isBlocked = response.isBlocked ?? (effectiveStatus === null || effectiveStatus !== null && BLOCKING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
2214
|
+
return {
|
|
2215
|
+
hasAccess,
|
|
2216
|
+
effectiveStatus,
|
|
2217
|
+
isGrace,
|
|
2218
|
+
isBlocked: isBlocked || !hasAccess,
|
|
2219
|
+
allowGrace,
|
|
2220
|
+
failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
|
|
2221
|
+
denialReason: resolveServiceAccessDenialReason({ effectiveStatus, hasAccess, isGrace }, allowGrace),
|
|
2222
|
+
organizationId: response.organizationId,
|
|
2223
|
+
subscriptionId: response.subscriptionId,
|
|
2224
|
+
status: response.status,
|
|
2225
|
+
planCode: response.planCode,
|
|
2226
|
+
currentPeriodEnd: response.currentPeriodEnd,
|
|
2227
|
+
gracePeriodEndsAt: response.gracePeriodEndsAt ?? null,
|
|
2228
|
+
reactivatable: response.reactivatable ?? false
|
|
2229
|
+
};
|
|
2230
|
+
}
|
|
2231
|
+
function failClosedServiceAccessDecision(params, error) {
|
|
2232
|
+
return {
|
|
2233
|
+
hasAccess: false,
|
|
2234
|
+
effectiveStatus: null,
|
|
2235
|
+
isGrace: false,
|
|
2236
|
+
isBlocked: true,
|
|
2237
|
+
allowGrace: params.allowGrace ?? DEFAULT_ALLOW_GRACE,
|
|
2238
|
+
failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
|
|
2239
|
+
denialReason: "ffid_unreachable",
|
|
2240
|
+
organizationId: params.organizationId || null,
|
|
2241
|
+
subscriptionId: null,
|
|
2242
|
+
status: null,
|
|
2243
|
+
planCode: null,
|
|
2244
|
+
currentPeriodEnd: null,
|
|
2245
|
+
gracePeriodEndsAt: null,
|
|
2246
|
+
reactivatable: false,
|
|
2247
|
+
error
|
|
2248
|
+
};
|
|
2249
|
+
}
|
|
2183
2250
|
function resolveRedirectUri(raw, logger) {
|
|
2184
2251
|
if (raw === null) return null;
|
|
2185
2252
|
try {
|
|
@@ -2418,6 +2485,57 @@ function createFFIDClient(config) {
|
|
|
2418
2485
|
`${EXT_CHECK_ENDPOINT}?${query.toString()}`
|
|
2419
2486
|
);
|
|
2420
2487
|
}
|
|
2488
|
+
async function checkServiceAccess(params) {
|
|
2489
|
+
const failPolicy = params.failPolicy ?? DEFAULT_SERVICE_ACCESS_FAIL_POLICY;
|
|
2490
|
+
if (failPolicy !== DEFAULT_SERVICE_ACCESS_FAIL_POLICY) {
|
|
2491
|
+
return {
|
|
2492
|
+
error: createError(
|
|
2493
|
+
"VALIDATION_ERROR",
|
|
2494
|
+
`failPolicy \u306F ${DEFAULT_SERVICE_ACCESS_FAIL_POLICY} \u306E\u307F\u6307\u5B9A\u3067\u304D\u307E\u3059`
|
|
2495
|
+
)
|
|
2496
|
+
};
|
|
2497
|
+
}
|
|
2498
|
+
const subscriptionParams = {
|
|
2499
|
+
organizationId: params.organizationId
|
|
2500
|
+
};
|
|
2501
|
+
if (params.userId !== void 0) {
|
|
2502
|
+
subscriptionParams.userId = params.userId;
|
|
2503
|
+
}
|
|
2504
|
+
const subscriptionResult = await checkSubscription(subscriptionParams);
|
|
2505
|
+
if (subscriptionResult.error) {
|
|
2506
|
+
if (subscriptionResult.error.code === "VALIDATION_ERROR") {
|
|
2507
|
+
return { error: subscriptionResult.error };
|
|
2508
|
+
}
|
|
2509
|
+
return {
|
|
2510
|
+
data: failClosedServiceAccessDecision(params, subscriptionResult.error)
|
|
2511
|
+
};
|
|
2512
|
+
}
|
|
2513
|
+
return {
|
|
2514
|
+
data: toServiceAccessDecision(
|
|
2515
|
+
subscriptionResult.data,
|
|
2516
|
+
params.allowGrace ?? DEFAULT_ALLOW_GRACE
|
|
2517
|
+
)
|
|
2518
|
+
};
|
|
2519
|
+
}
|
|
2520
|
+
async function requireServiceAccess(params) {
|
|
2521
|
+
const result = await checkServiceAccess(params);
|
|
2522
|
+
if (result.error) {
|
|
2523
|
+
return result;
|
|
2524
|
+
}
|
|
2525
|
+
if (!result.data.hasAccess) {
|
|
2526
|
+
const error = createError(
|
|
2527
|
+
SERVICE_ACCESS_DENIED_CODE,
|
|
2528
|
+
`FFID service access denied: ${result.data.denialReason ?? "unknown"}`
|
|
2529
|
+
);
|
|
2530
|
+
if (result.data.error) {
|
|
2531
|
+
error.details = { cause: result.data.error };
|
|
2532
|
+
}
|
|
2533
|
+
return {
|
|
2534
|
+
error
|
|
2535
|
+
};
|
|
2536
|
+
}
|
|
2537
|
+
return result;
|
|
2538
|
+
}
|
|
2421
2539
|
const { createCheckoutSession, createPortalSession } = createBillingMethods({
|
|
2422
2540
|
fetchWithAuth,
|
|
2423
2541
|
createError
|
|
@@ -2516,6 +2634,8 @@ function createFFIDClient(config) {
|
|
|
2516
2634
|
exchangeCodeForTokens,
|
|
2517
2635
|
refreshAccessToken,
|
|
2518
2636
|
checkSubscription,
|
|
2637
|
+
checkServiceAccess,
|
|
2638
|
+
requireServiceAccess,
|
|
2519
2639
|
listMembers,
|
|
2520
2640
|
updateMemberRole,
|
|
2521
2641
|
removeMember,
|
package/dist/server/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-
|
|
2
|
-
export { f as FFIDCacheConfig, g as FFIDClient, h as FFIDConfig, i as FFIDOrganization, j as FFIDOtpSendResponse, k as FFIDOtpVerifyResponse, l as FFIDPasswordResetConfirmResponse, m as FFIDPasswordResetResponse, n as FFIDPasswordResetVerifyResponse, o as FFIDProfileCallOptions, p as FFIDResetSessionResponse, q as FFIDSubscription, r as FFIDUpdateUserProfileRequest, s as FFIDUser, t as FFIDUserProfile, T as TokenData, u as TokenStore, v as createFFIDClient, w as createTokenStore } from '../ffid-client-
|
|
1
|
+
import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-CKMGqqPi.cjs';
|
|
2
|
+
export { f as FFIDCacheConfig, g as FFIDClient, h as FFIDConfig, i as FFIDOrganization, j as FFIDOtpSendResponse, k as FFIDOtpVerifyResponse, l as FFIDPasswordResetConfirmResponse, m as FFIDPasswordResetResponse, n as FFIDPasswordResetVerifyResponse, o as FFIDProfileCallOptions, p as FFIDResetSessionResponse, q as FFIDSubscription, r as FFIDUpdateUserProfileRequest, s as FFIDUser, t as FFIDUserProfile, T as TokenData, u as TokenStore, v as createFFIDClient, w as createTokenStore } from '../ffid-client-CKMGqqPi.cjs';
|
|
3
3
|
export { D as DEFAULT_API_BASE_URL, a as DEFAULT_OAUTH_SCOPES } from '../constants-D61jqRIO.cjs';
|
|
4
|
+
import '../types-5g_Bg6Ey.cjs';
|
|
4
5
|
|
|
5
6
|
/** Token verification - verifyAccessToken() implementation */
|
|
6
7
|
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-
|
|
2
|
-
export { f as FFIDCacheConfig, g as FFIDClient, h as FFIDConfig, i as FFIDOrganization, j as FFIDOtpSendResponse, k as FFIDOtpVerifyResponse, l as FFIDPasswordResetConfirmResponse, m as FFIDPasswordResetResponse, n as FFIDPasswordResetVerifyResponse, o as FFIDProfileCallOptions, p as FFIDResetSessionResponse, q as FFIDSubscription, r as FFIDUpdateUserProfileRequest, s as FFIDUser, t as FFIDUserProfile, T as TokenData, u as TokenStore, v as createFFIDClient, w as createTokenStore } from '../ffid-client-
|
|
1
|
+
import { F as FFIDLogger, a as FFIDError, b as FFIDCacheAdapter, c as FFIDVerifyAccessTokenOptions, d as FFIDApiResponse, e as FFIDOAuthUserInfo } from '../ffid-client-CUOFknXy.js';
|
|
2
|
+
export { f as FFIDCacheConfig, g as FFIDClient, h as FFIDConfig, i as FFIDOrganization, j as FFIDOtpSendResponse, k as FFIDOtpVerifyResponse, l as FFIDPasswordResetConfirmResponse, m as FFIDPasswordResetResponse, n as FFIDPasswordResetVerifyResponse, o as FFIDProfileCallOptions, p as FFIDResetSessionResponse, q as FFIDSubscription, r as FFIDUpdateUserProfileRequest, s as FFIDUser, t as FFIDUserProfile, T as TokenData, u as TokenStore, v as createFFIDClient, w as createTokenStore } from '../ffid-client-CUOFknXy.js';
|
|
3
3
|
export { D as DEFAULT_API_BASE_URL, a as DEFAULT_OAUTH_SCOPES } from '../constants-D61jqRIO.js';
|
|
4
|
+
import '../types-5g_Bg6Ey.js';
|
|
4
5
|
|
|
5
6
|
/** Token verification - verifyAccessToken() implementation */
|
|
6
7
|
|
package/dist/server/index.js
CHANGED
|
@@ -802,7 +802,7 @@ function createProfileMethods(deps) {
|
|
|
802
802
|
}
|
|
803
803
|
|
|
804
804
|
// src/client/version-check.ts
|
|
805
|
-
var SDK_VERSION = "4.
|
|
805
|
+
var SDK_VERSION = "4.2.0";
|
|
806
806
|
var SDK_USER_AGENT = `FFID-SDK/${SDK_VERSION} (TypeScript)`;
|
|
807
807
|
var SDK_VERSION_HEADER = "X-FFID-SDK-Version";
|
|
808
808
|
function sdkHeaders() {
|
|
@@ -2179,6 +2179,73 @@ var FFID_ERROR_CODES = {
|
|
|
2179
2179
|
TOKEN_VERIFICATION_ERROR: "TOKEN_VERIFICATION_ERROR"
|
|
2180
2180
|
};
|
|
2181
2181
|
var EXT_CHECK_ENDPOINT = "/api/v1/subscriptions/ext/check";
|
|
2182
|
+
var DEFAULT_ALLOW_GRACE = true;
|
|
2183
|
+
var DEFAULT_SERVICE_ACCESS_FAIL_POLICY = "failClosed";
|
|
2184
|
+
var SERVICE_ACCESS_DENIED_CODE = "SERVICE_ACCESS_DENIED";
|
|
2185
|
+
var ACCESS_GRANTING_EFFECTIVE_STATUSES = ["active", "past_due_grace"];
|
|
2186
|
+
var BLOCKING_EFFECTIVE_STATUSES = [
|
|
2187
|
+
"blocked",
|
|
2188
|
+
"canceled",
|
|
2189
|
+
"expired",
|
|
2190
|
+
"trial_expired"
|
|
2191
|
+
];
|
|
2192
|
+
function resolveServiceAccessDenialReason(params, allowGrace) {
|
|
2193
|
+
if (params.hasAccess) {
|
|
2194
|
+
return null;
|
|
2195
|
+
}
|
|
2196
|
+
if (params.effectiveStatus === null) {
|
|
2197
|
+
return "no_subscription";
|
|
2198
|
+
}
|
|
2199
|
+
if (params.isGrace && !allowGrace) {
|
|
2200
|
+
return "grace_disallowed";
|
|
2201
|
+
}
|
|
2202
|
+
if (params.effectiveStatus === "active" || params.effectiveStatus === "past_due_grace") {
|
|
2203
|
+
return "blocked";
|
|
2204
|
+
}
|
|
2205
|
+
return params.effectiveStatus;
|
|
2206
|
+
}
|
|
2207
|
+
function toServiceAccessDecision(response, allowGrace) {
|
|
2208
|
+
const effectiveStatus = response.effectiveStatus ?? null;
|
|
2209
|
+
const serverHasAccess = response.hasAccess ?? (effectiveStatus !== null && ACCESS_GRANTING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
2210
|
+
const isGrace = response.isGrace ?? effectiveStatus === "past_due_grace";
|
|
2211
|
+
const hasAccess = serverHasAccess && (allowGrace || !isGrace);
|
|
2212
|
+
const isBlocked = response.isBlocked ?? (effectiveStatus === null || effectiveStatus !== null && BLOCKING_EFFECTIVE_STATUSES.includes(effectiveStatus));
|
|
2213
|
+
return {
|
|
2214
|
+
hasAccess,
|
|
2215
|
+
effectiveStatus,
|
|
2216
|
+
isGrace,
|
|
2217
|
+
isBlocked: isBlocked || !hasAccess,
|
|
2218
|
+
allowGrace,
|
|
2219
|
+
failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
|
|
2220
|
+
denialReason: resolveServiceAccessDenialReason({ effectiveStatus, hasAccess, isGrace }, allowGrace),
|
|
2221
|
+
organizationId: response.organizationId,
|
|
2222
|
+
subscriptionId: response.subscriptionId,
|
|
2223
|
+
status: response.status,
|
|
2224
|
+
planCode: response.planCode,
|
|
2225
|
+
currentPeriodEnd: response.currentPeriodEnd,
|
|
2226
|
+
gracePeriodEndsAt: response.gracePeriodEndsAt ?? null,
|
|
2227
|
+
reactivatable: response.reactivatable ?? false
|
|
2228
|
+
};
|
|
2229
|
+
}
|
|
2230
|
+
function failClosedServiceAccessDecision(params, error) {
|
|
2231
|
+
return {
|
|
2232
|
+
hasAccess: false,
|
|
2233
|
+
effectiveStatus: null,
|
|
2234
|
+
isGrace: false,
|
|
2235
|
+
isBlocked: true,
|
|
2236
|
+
allowGrace: params.allowGrace ?? DEFAULT_ALLOW_GRACE,
|
|
2237
|
+
failPolicy: DEFAULT_SERVICE_ACCESS_FAIL_POLICY,
|
|
2238
|
+
denialReason: "ffid_unreachable",
|
|
2239
|
+
organizationId: params.organizationId || null,
|
|
2240
|
+
subscriptionId: null,
|
|
2241
|
+
status: null,
|
|
2242
|
+
planCode: null,
|
|
2243
|
+
currentPeriodEnd: null,
|
|
2244
|
+
gracePeriodEndsAt: null,
|
|
2245
|
+
reactivatable: false,
|
|
2246
|
+
error
|
|
2247
|
+
};
|
|
2248
|
+
}
|
|
2182
2249
|
function resolveRedirectUri(raw, logger) {
|
|
2183
2250
|
if (raw === null) return null;
|
|
2184
2251
|
try {
|
|
@@ -2417,6 +2484,57 @@ function createFFIDClient(config) {
|
|
|
2417
2484
|
`${EXT_CHECK_ENDPOINT}?${query.toString()}`
|
|
2418
2485
|
);
|
|
2419
2486
|
}
|
|
2487
|
+
async function checkServiceAccess(params) {
|
|
2488
|
+
const failPolicy = params.failPolicy ?? DEFAULT_SERVICE_ACCESS_FAIL_POLICY;
|
|
2489
|
+
if (failPolicy !== DEFAULT_SERVICE_ACCESS_FAIL_POLICY) {
|
|
2490
|
+
return {
|
|
2491
|
+
error: createError(
|
|
2492
|
+
"VALIDATION_ERROR",
|
|
2493
|
+
`failPolicy \u306F ${DEFAULT_SERVICE_ACCESS_FAIL_POLICY} \u306E\u307F\u6307\u5B9A\u3067\u304D\u307E\u3059`
|
|
2494
|
+
)
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
const subscriptionParams = {
|
|
2498
|
+
organizationId: params.organizationId
|
|
2499
|
+
};
|
|
2500
|
+
if (params.userId !== void 0) {
|
|
2501
|
+
subscriptionParams.userId = params.userId;
|
|
2502
|
+
}
|
|
2503
|
+
const subscriptionResult = await checkSubscription(subscriptionParams);
|
|
2504
|
+
if (subscriptionResult.error) {
|
|
2505
|
+
if (subscriptionResult.error.code === "VALIDATION_ERROR") {
|
|
2506
|
+
return { error: subscriptionResult.error };
|
|
2507
|
+
}
|
|
2508
|
+
return {
|
|
2509
|
+
data: failClosedServiceAccessDecision(params, subscriptionResult.error)
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
return {
|
|
2513
|
+
data: toServiceAccessDecision(
|
|
2514
|
+
subscriptionResult.data,
|
|
2515
|
+
params.allowGrace ?? DEFAULT_ALLOW_GRACE
|
|
2516
|
+
)
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
async function requireServiceAccess(params) {
|
|
2520
|
+
const result = await checkServiceAccess(params);
|
|
2521
|
+
if (result.error) {
|
|
2522
|
+
return result;
|
|
2523
|
+
}
|
|
2524
|
+
if (!result.data.hasAccess) {
|
|
2525
|
+
const error = createError(
|
|
2526
|
+
SERVICE_ACCESS_DENIED_CODE,
|
|
2527
|
+
`FFID service access denied: ${result.data.denialReason ?? "unknown"}`
|
|
2528
|
+
);
|
|
2529
|
+
if (result.data.error) {
|
|
2530
|
+
error.details = { cause: result.data.error };
|
|
2531
|
+
}
|
|
2532
|
+
return {
|
|
2533
|
+
error
|
|
2534
|
+
};
|
|
2535
|
+
}
|
|
2536
|
+
return result;
|
|
2537
|
+
}
|
|
2420
2538
|
const { createCheckoutSession, createPortalSession } = createBillingMethods({
|
|
2421
2539
|
fetchWithAuth,
|
|
2422
2540
|
createError
|
|
@@ -2515,6 +2633,8 @@ function createFFIDClient(config) {
|
|
|
2515
2633
|
exchangeCodeForTokens,
|
|
2516
2634
|
refreshAccessToken,
|
|
2517
2635
|
checkSubscription,
|
|
2636
|
+
checkServiceAccess,
|
|
2637
|
+
requireServiceAccess,
|
|
2518
2638
|
listMembers,
|
|
2519
2639
|
updateMemberRole,
|
|
2520
2640
|
removeMember,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { g as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-
|
|
1
|
+
import { g as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-CKMGqqPi.cjs';
|
|
2
|
+
import '../../types-5g_Bg6Ey.cjs';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* FFID SDK - Test mode client (E2E / integration test bypass)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { g as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-
|
|
1
|
+
import { g as FFIDClient, e as FFIDOAuthUserInfo } from '../../ffid-client-CUOFknXy.js';
|
|
2
|
+
import '../../types-5g_Bg6Ey.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* FFID SDK - Test mode client (E2E / integration test bypass)
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscription access-control types (Chain of Pacts / Issue #2443).
|
|
3
|
+
*
|
|
4
|
+
* Defines `EffectiveSubscriptionStatus` — the semantic status surfaced by
|
|
5
|
+
* `/api/v1/subscriptions/ext/check` for external services that need a single
|
|
6
|
+
* value to drive access-control decisions. Mirrors the server-side type in
|
|
7
|
+
* `src/lib/common/subscription-helpers.ts` so the FFID backend, SDK, and
|
|
8
|
+
* consuming services agree on the same vocabulary.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Semantic subscription status used for access-control decisions by external
|
|
12
|
+
* services.
|
|
13
|
+
*
|
|
14
|
+
* Unlike the raw DB `FFIDSubscriptionStatus` (which keeps the Stripe-aligned
|
|
15
|
+
* status machine, e.g. `past_due` / `incomplete` / `incomplete_expired`), this
|
|
16
|
+
* narrowed union flattens dunning-window vs. hard-block cases so callers can
|
|
17
|
+
* branch on a single value:
|
|
18
|
+
*
|
|
19
|
+
* - `active` — normal paying subscription; grant full access.
|
|
20
|
+
* - `past_due_grace` — payment failed but FFID is still retrying. Service
|
|
21
|
+
* SHOULD keep access and surface a recovery banner.
|
|
22
|
+
* - `blocked` — payment dunning exhausted (`past_due` over grace,
|
|
23
|
+
* `unpaid`, `incomplete_expired`, `paused`, `incomplete`). Deny access.
|
|
24
|
+
* - `canceled` — contract ended (voluntary or auto-cancel). Deny access;
|
|
25
|
+
* check the accompanying `reactivatable` flag before showing a restart CTA.
|
|
26
|
+
* - `trial_expired` — `status = 'trialing'` but the trial end is in the past.
|
|
27
|
+
* DB row is still `trialing`; deny access and prompt for a paid plan.
|
|
28
|
+
* - `expired` — `status = 'active'` but `current_period_end` is in the past.
|
|
29
|
+
* This is the FFID-internal runtime-expired case (see
|
|
30
|
+
* `getEffectiveSubscriptionStatus` on the server). Deny access.
|
|
31
|
+
*
|
|
32
|
+
* @see /api/v1/subscriptions/ext/check
|
|
33
|
+
* @see docs/03-implementation/EXPIRED_CONTRACT_HANDLING.md
|
|
34
|
+
*/
|
|
35
|
+
type EffectiveSubscriptionStatus = 'active' | 'past_due_grace' | 'blocked' | 'canceled' | 'trial_expired' | 'expired';
|
|
36
|
+
|
|
37
|
+
export type { EffectiveSubscriptionStatus as E };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscription access-control types (Chain of Pacts / Issue #2443).
|
|
3
|
+
*
|
|
4
|
+
* Defines `EffectiveSubscriptionStatus` — the semantic status surfaced by
|
|
5
|
+
* `/api/v1/subscriptions/ext/check` for external services that need a single
|
|
6
|
+
* value to drive access-control decisions. Mirrors the server-side type in
|
|
7
|
+
* `src/lib/common/subscription-helpers.ts` so the FFID backend, SDK, and
|
|
8
|
+
* consuming services agree on the same vocabulary.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Semantic subscription status used for access-control decisions by external
|
|
12
|
+
* services.
|
|
13
|
+
*
|
|
14
|
+
* Unlike the raw DB `FFIDSubscriptionStatus` (which keeps the Stripe-aligned
|
|
15
|
+
* status machine, e.g. `past_due` / `incomplete` / `incomplete_expired`), this
|
|
16
|
+
* narrowed union flattens dunning-window vs. hard-block cases so callers can
|
|
17
|
+
* branch on a single value:
|
|
18
|
+
*
|
|
19
|
+
* - `active` — normal paying subscription; grant full access.
|
|
20
|
+
* - `past_due_grace` — payment failed but FFID is still retrying. Service
|
|
21
|
+
* SHOULD keep access and surface a recovery banner.
|
|
22
|
+
* - `blocked` — payment dunning exhausted (`past_due` over grace,
|
|
23
|
+
* `unpaid`, `incomplete_expired`, `paused`, `incomplete`). Deny access.
|
|
24
|
+
* - `canceled` — contract ended (voluntary or auto-cancel). Deny access;
|
|
25
|
+
* check the accompanying `reactivatable` flag before showing a restart CTA.
|
|
26
|
+
* - `trial_expired` — `status = 'trialing'` but the trial end is in the past.
|
|
27
|
+
* DB row is still `trialing`; deny access and prompt for a paid plan.
|
|
28
|
+
* - `expired` — `status = 'active'` but `current_period_end` is in the past.
|
|
29
|
+
* This is the FFID-internal runtime-expired case (see
|
|
30
|
+
* `getEffectiveSubscriptionStatus` on the server). Deny access.
|
|
31
|
+
*
|
|
32
|
+
* @see /api/v1/subscriptions/ext/check
|
|
33
|
+
* @see docs/03-implementation/EXPIRED_CONTRACT_HANDLING.md
|
|
34
|
+
*/
|
|
35
|
+
type EffectiveSubscriptionStatus = 'active' | 'past_due_grace' | 'blocked' | 'canceled' | 'trial_expired' | 'expired';
|
|
36
|
+
|
|
37
|
+
export type { EffectiveSubscriptionStatus as E };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { E as EffectiveSubscriptionStatus } from '../types-5g_Bg6Ey.cjs';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* FFID Webhook SDK Constants
|
|
3
5
|
*
|
|
@@ -43,13 +45,16 @@ declare class FFIDWebhookPayloadError extends FFIDWebhookError {
|
|
|
43
45
|
* Types for receiving and verifying FeelFlow ID webhook events.
|
|
44
46
|
* Used by external services to handle real-time event notifications.
|
|
45
47
|
*/
|
|
48
|
+
|
|
46
49
|
/** All supported webhook event types */
|
|
47
|
-
type FFIDWebhookEventType = 'subscription.created' | 'subscription.updated' | 'subscription.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.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';
|
|
48
51
|
interface FFIDSubscriptionCreatedPayload {
|
|
49
52
|
subscriptionId: string;
|
|
50
53
|
organizationId?: string;
|
|
51
54
|
plan?: string;
|
|
52
55
|
status?: string;
|
|
56
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
57
|
+
gracePeriodEndsAt?: string | null;
|
|
53
58
|
}
|
|
54
59
|
interface FFIDSubscriptionUpdatedPayload {
|
|
55
60
|
subscriptionId: string;
|
|
@@ -57,6 +62,8 @@ interface FFIDSubscriptionUpdatedPayload {
|
|
|
57
62
|
plan?: string;
|
|
58
63
|
previousPlan?: string;
|
|
59
64
|
status?: string;
|
|
65
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
66
|
+
gracePeriodEndsAt?: string | null;
|
|
60
67
|
}
|
|
61
68
|
interface FFIDSubscriptionCanceledPayload {
|
|
62
69
|
/** FFID subscription UUID. */
|
|
@@ -86,6 +93,52 @@ interface FFIDSubscriptionCanceledPayload {
|
|
|
86
93
|
* when Stripe runs out the paid period before emitting the deletion event.
|
|
87
94
|
*/
|
|
88
95
|
expiredAt?: string;
|
|
96
|
+
/** Cancellation always leaves the canonical access-control status as `canceled`. */
|
|
97
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
98
|
+
/** Always null for cancellation events because no grace window remains. */
|
|
99
|
+
gracePeriodEndsAt?: string | null;
|
|
100
|
+
}
|
|
101
|
+
interface FFIDSubscriptionDowngradeScheduledPayload {
|
|
102
|
+
/** FFID subscription UUID. */
|
|
103
|
+
subscriptionId: string;
|
|
104
|
+
/** Organization UUID that owns the subscription. */
|
|
105
|
+
organizationId: string;
|
|
106
|
+
/** Plan UUID currently active on the subscription. */
|
|
107
|
+
currentPlanId: string;
|
|
108
|
+
/** Plan UUID scheduled to become active at period end. */
|
|
109
|
+
newPlanId: string;
|
|
110
|
+
/** Billing interval carried by the target period, typically 'monthly' or 'yearly'. */
|
|
111
|
+
billingInterval: string;
|
|
112
|
+
/** ISO timestamp when the downgrade was scheduled. */
|
|
113
|
+
scheduledAt: string;
|
|
114
|
+
/** ISO timestamp when the scheduled downgrade should take effect. */
|
|
115
|
+
effectiveAt: string;
|
|
116
|
+
}
|
|
117
|
+
interface FFIDSubscriptionDowngradeAppliedPayload {
|
|
118
|
+
/** FFID subscription UUID. */
|
|
119
|
+
subscriptionId: string;
|
|
120
|
+
/** Organization UUID that owns the subscription. */
|
|
121
|
+
organizationId: string;
|
|
122
|
+
/** Plan UUID active before the pending downgrade was applied. */
|
|
123
|
+
previousPlanId: string;
|
|
124
|
+
/** Plan UUID that became active after the downgrade was applied. */
|
|
125
|
+
newPlanId: string;
|
|
126
|
+
/** Billing interval on the applied downgraded plan, typically 'monthly' or 'yearly'. */
|
|
127
|
+
billingInterval: string;
|
|
128
|
+
/** ISO timestamp when FFID applied the pending downgrade. */
|
|
129
|
+
appliedAt: string;
|
|
130
|
+
}
|
|
131
|
+
interface FFIDSubscriptionDowngradeCanceledPayload {
|
|
132
|
+
/** FFID subscription UUID. */
|
|
133
|
+
subscriptionId: string;
|
|
134
|
+
/** Organization UUID that owns the subscription. */
|
|
135
|
+
organizationId: string;
|
|
136
|
+
/** Plan UUID that had been pending but was canceled before taking effect. */
|
|
137
|
+
canceledPlanId: string;
|
|
138
|
+
/** Plan UUID that remains active after canceling the pending downgrade. */
|
|
139
|
+
currentPlanId: string;
|
|
140
|
+
/** ISO timestamp when the pending downgrade was canceled. */
|
|
141
|
+
canceledAt: string;
|
|
89
142
|
}
|
|
90
143
|
interface FFIDSubscriptionTrialEndingPayload {
|
|
91
144
|
subscriptionId: string;
|
|
@@ -130,6 +183,13 @@ interface FFIDSubscriptionPaymentFailedPayload {
|
|
|
130
183
|
* `null` means already blocking.
|
|
131
184
|
*/
|
|
132
185
|
graceUntil?: string | null;
|
|
186
|
+
/** Canonical FFID access-control status derived from payment-failure severity. */
|
|
187
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
188
|
+
/**
|
|
189
|
+
* Alias of `graceUntil` for canonical access payloads; services should prefer
|
|
190
|
+
* this field when sharing code with `/subscriptions/ext/check`.
|
|
191
|
+
*/
|
|
192
|
+
gracePeriodEndsAt?: string | null;
|
|
133
193
|
/**
|
|
134
194
|
* `true` when the FFID server could not resolve `stripeSubscriptionId` to an
|
|
135
195
|
* FFID subscription row (e.g. race with a not-yet-synced sub, or invoice
|
|
@@ -221,6 +281,9 @@ interface FFIDWebhookEventMap {
|
|
|
221
281
|
'subscription.created': FFIDSubscriptionCreatedPayload;
|
|
222
282
|
'subscription.updated': FFIDSubscriptionUpdatedPayload;
|
|
223
283
|
'subscription.canceled': FFIDSubscriptionCanceledPayload;
|
|
284
|
+
'subscription.downgrade_scheduled': FFIDSubscriptionDowngradeScheduledPayload;
|
|
285
|
+
'subscription.downgrade_applied': FFIDSubscriptionDowngradeAppliedPayload;
|
|
286
|
+
'subscription.downgrade_canceled': FFIDSubscriptionDowngradeCanceledPayload;
|
|
224
287
|
'subscription.trial_ending': FFIDSubscriptionTrialEndingPayload;
|
|
225
288
|
'subscription.payment_failed': FFIDSubscriptionPaymentFailedPayload;
|
|
226
289
|
'user.created': FFIDUserCreatedPayload;
|
|
@@ -363,4 +426,4 @@ declare function createFFIDWebhookHandler(config: FFIDWebhookHandlerConfig): {
|
|
|
363
426
|
/** Type of the FFID Webhook handler */
|
|
364
427
|
type FFIDWebhookHandler = ReturnType<typeof createFFIDWebhookHandler>;
|
|
365
428
|
|
|
366
|
-
export { DEFAULT_TOLERANCE_SECONDS, type FFIDLegalAgreementRequiredPayload, type FFIDLegalDocumentUpdatedPayload, type FFIDOrganizationCreatedPayload, type FFIDOrganizationMemberAddedPayload, type FFIDOrganizationMemberRemovedPayload, type FFIDOrganizationMemberRoleChangedPayload, type FFIDOrganizationUpdatedPayload, type FFIDSubscriptionCanceledPayload, type FFIDSubscriptionCreatedPayload, 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 };
|
|
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 };
|
package/dist/webhooks/index.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { E as EffectiveSubscriptionStatus } from '../types-5g_Bg6Ey.js';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* FFID Webhook SDK Constants
|
|
3
5
|
*
|
|
@@ -43,13 +45,16 @@ declare class FFIDWebhookPayloadError extends FFIDWebhookError {
|
|
|
43
45
|
* Types for receiving and verifying FeelFlow ID webhook events.
|
|
44
46
|
* Used by external services to handle real-time event notifications.
|
|
45
47
|
*/
|
|
48
|
+
|
|
46
49
|
/** All supported webhook event types */
|
|
47
|
-
type FFIDWebhookEventType = 'subscription.created' | 'subscription.updated' | 'subscription.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.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';
|
|
48
51
|
interface FFIDSubscriptionCreatedPayload {
|
|
49
52
|
subscriptionId: string;
|
|
50
53
|
organizationId?: string;
|
|
51
54
|
plan?: string;
|
|
52
55
|
status?: string;
|
|
56
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
57
|
+
gracePeriodEndsAt?: string | null;
|
|
53
58
|
}
|
|
54
59
|
interface FFIDSubscriptionUpdatedPayload {
|
|
55
60
|
subscriptionId: string;
|
|
@@ -57,6 +62,8 @@ interface FFIDSubscriptionUpdatedPayload {
|
|
|
57
62
|
plan?: string;
|
|
58
63
|
previousPlan?: string;
|
|
59
64
|
status?: string;
|
|
65
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
66
|
+
gracePeriodEndsAt?: string | null;
|
|
60
67
|
}
|
|
61
68
|
interface FFIDSubscriptionCanceledPayload {
|
|
62
69
|
/** FFID subscription UUID. */
|
|
@@ -86,6 +93,52 @@ interface FFIDSubscriptionCanceledPayload {
|
|
|
86
93
|
* when Stripe runs out the paid period before emitting the deletion event.
|
|
87
94
|
*/
|
|
88
95
|
expiredAt?: string;
|
|
96
|
+
/** Cancellation always leaves the canonical access-control status as `canceled`. */
|
|
97
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
98
|
+
/** Always null for cancellation events because no grace window remains. */
|
|
99
|
+
gracePeriodEndsAt?: string | null;
|
|
100
|
+
}
|
|
101
|
+
interface FFIDSubscriptionDowngradeScheduledPayload {
|
|
102
|
+
/** FFID subscription UUID. */
|
|
103
|
+
subscriptionId: string;
|
|
104
|
+
/** Organization UUID that owns the subscription. */
|
|
105
|
+
organizationId: string;
|
|
106
|
+
/** Plan UUID currently active on the subscription. */
|
|
107
|
+
currentPlanId: string;
|
|
108
|
+
/** Plan UUID scheduled to become active at period end. */
|
|
109
|
+
newPlanId: string;
|
|
110
|
+
/** Billing interval carried by the target period, typically 'monthly' or 'yearly'. */
|
|
111
|
+
billingInterval: string;
|
|
112
|
+
/** ISO timestamp when the downgrade was scheduled. */
|
|
113
|
+
scheduledAt: string;
|
|
114
|
+
/** ISO timestamp when the scheduled downgrade should take effect. */
|
|
115
|
+
effectiveAt: string;
|
|
116
|
+
}
|
|
117
|
+
interface FFIDSubscriptionDowngradeAppliedPayload {
|
|
118
|
+
/** FFID subscription UUID. */
|
|
119
|
+
subscriptionId: string;
|
|
120
|
+
/** Organization UUID that owns the subscription. */
|
|
121
|
+
organizationId: string;
|
|
122
|
+
/** Plan UUID active before the pending downgrade was applied. */
|
|
123
|
+
previousPlanId: string;
|
|
124
|
+
/** Plan UUID that became active after the downgrade was applied. */
|
|
125
|
+
newPlanId: string;
|
|
126
|
+
/** Billing interval on the applied downgraded plan, typically 'monthly' or 'yearly'. */
|
|
127
|
+
billingInterval: string;
|
|
128
|
+
/** ISO timestamp when FFID applied the pending downgrade. */
|
|
129
|
+
appliedAt: string;
|
|
130
|
+
}
|
|
131
|
+
interface FFIDSubscriptionDowngradeCanceledPayload {
|
|
132
|
+
/** FFID subscription UUID. */
|
|
133
|
+
subscriptionId: string;
|
|
134
|
+
/** Organization UUID that owns the subscription. */
|
|
135
|
+
organizationId: string;
|
|
136
|
+
/** Plan UUID that had been pending but was canceled before taking effect. */
|
|
137
|
+
canceledPlanId: string;
|
|
138
|
+
/** Plan UUID that remains active after canceling the pending downgrade. */
|
|
139
|
+
currentPlanId: string;
|
|
140
|
+
/** ISO timestamp when the pending downgrade was canceled. */
|
|
141
|
+
canceledAt: string;
|
|
89
142
|
}
|
|
90
143
|
interface FFIDSubscriptionTrialEndingPayload {
|
|
91
144
|
subscriptionId: string;
|
|
@@ -130,6 +183,13 @@ interface FFIDSubscriptionPaymentFailedPayload {
|
|
|
130
183
|
* `null` means already blocking.
|
|
131
184
|
*/
|
|
132
185
|
graceUntil?: string | null;
|
|
186
|
+
/** Canonical FFID access-control status derived from payment-failure severity. */
|
|
187
|
+
effectiveStatus?: EffectiveSubscriptionStatus;
|
|
188
|
+
/**
|
|
189
|
+
* Alias of `graceUntil` for canonical access payloads; services should prefer
|
|
190
|
+
* this field when sharing code with `/subscriptions/ext/check`.
|
|
191
|
+
*/
|
|
192
|
+
gracePeriodEndsAt?: string | null;
|
|
133
193
|
/**
|
|
134
194
|
* `true` when the FFID server could not resolve `stripeSubscriptionId` to an
|
|
135
195
|
* FFID subscription row (e.g. race with a not-yet-synced sub, or invoice
|
|
@@ -221,6 +281,9 @@ interface FFIDWebhookEventMap {
|
|
|
221
281
|
'subscription.created': FFIDSubscriptionCreatedPayload;
|
|
222
282
|
'subscription.updated': FFIDSubscriptionUpdatedPayload;
|
|
223
283
|
'subscription.canceled': FFIDSubscriptionCanceledPayload;
|
|
284
|
+
'subscription.downgrade_scheduled': FFIDSubscriptionDowngradeScheduledPayload;
|
|
285
|
+
'subscription.downgrade_applied': FFIDSubscriptionDowngradeAppliedPayload;
|
|
286
|
+
'subscription.downgrade_canceled': FFIDSubscriptionDowngradeCanceledPayload;
|
|
224
287
|
'subscription.trial_ending': FFIDSubscriptionTrialEndingPayload;
|
|
225
288
|
'subscription.payment_failed': FFIDSubscriptionPaymentFailedPayload;
|
|
226
289
|
'user.created': FFIDUserCreatedPayload;
|
|
@@ -363,4 +426,4 @@ declare function createFFIDWebhookHandler(config: FFIDWebhookHandlerConfig): {
|
|
|
363
426
|
/** Type of the FFID Webhook handler */
|
|
364
427
|
type FFIDWebhookHandler = ReturnType<typeof createFFIDWebhookHandler>;
|
|
365
428
|
|
|
366
|
-
export { DEFAULT_TOLERANCE_SECONDS, type FFIDLegalAgreementRequiredPayload, type FFIDLegalDocumentUpdatedPayload, type FFIDOrganizationCreatedPayload, type FFIDOrganizationMemberAddedPayload, type FFIDOrganizationMemberRemovedPayload, type FFIDOrganizationMemberRoleChangedPayload, type FFIDOrganizationUpdatedPayload, type FFIDSubscriptionCanceledPayload, type FFIDSubscriptionCreatedPayload, 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 };
|
|
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 };
|