@odla-ai/chapter 0.56.2 → 0.57.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 +57 -0
- package/dist/{chunk-E7CB5K2D.js → chunk-CKC6X5H2.js} +47 -3
- package/dist/chunk-CKC6X5H2.js.map +1 -0
- package/dist/{chunk-4M2PN5K3.js → chunk-FHKZVF5G.js} +3 -1
- package/dist/chunk-FHKZVF5G.js.map +1 -0
- package/dist/{chunk-ZAE24YKY.js → chunk-L2IPS2FQ.js} +51 -4
- package/dist/chunk-L2IPS2FQ.js.map +1 -0
- package/dist/{copy-context-CaUXIxUI.d.ts → copy-context-DE4YMAbz.d.ts} +1 -1
- package/dist/index.cjs +176 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -3
- package/dist/index.d.ts +36 -3
- package/dist/index.js +176 -13
- package/dist/index.js.map +1 -1
- package/dist/ui/admin/index.d.ts +4 -3
- package/dist/ui/admin/index.js +2 -2
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +3 -3
- package/dist/ui/member/index.d.ts +10 -3
- package/dist/ui/member/index.js +2 -2
- package/dist/worker/index.cjs +1558 -1125
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +149 -3
- package/dist/worker/index.d.ts +149 -3
- package/dist/worker/index.js +1558 -1125
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-4M2PN5K3.js.map +0 -1
- package/dist/chunk-E7CB5K2D.js.map +0 -1
- package/dist/chunk-ZAE24YKY.js.map +0 -1
package/dist/worker/index.d.cts
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import { CrmConfig, Crm, FieldConditions } from '@odla-ai/crm';
|
|
2
2
|
import { initAdmin } from '@odla-ai/db';
|
|
3
3
|
|
|
4
|
+
/** One membership tier a chapter offers. `priceCents: 0` means free. */
|
|
5
|
+
interface ChapterTier {
|
|
6
|
+
/** Stable slug, referenced by `applications.tierId`. Never renumbered. */
|
|
7
|
+
id: string;
|
|
8
|
+
/** The group this tier belongs to. */
|
|
9
|
+
groupId: string;
|
|
10
|
+
/** Display name, e.g. "Founding". */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Price in minor units. `0` is free and needs no Stripe price. */
|
|
13
|
+
priceCents: number;
|
|
14
|
+
/** ISO currency inherited from the group for legacy rows. */
|
|
15
|
+
currency?: string;
|
|
16
|
+
/** Recurring interval inherited from the group for legacy rows. */
|
|
17
|
+
interval?: "year" | "month";
|
|
18
|
+
/** Stripe price to subscribe. Required only when `priceCents > 0`. */
|
|
19
|
+
stripePriceId?: string | null;
|
|
20
|
+
/** Short description shown beside the tier on the join page. */
|
|
21
|
+
blurb?: string;
|
|
22
|
+
/** Ascending display order; ties fall back to `id` for a stable sort. */
|
|
23
|
+
sortOrder: number;
|
|
24
|
+
/** An inactive tier is retained for existing members but never offered. */
|
|
25
|
+
active: boolean;
|
|
26
|
+
}
|
|
4
27
|
/**
|
|
5
28
|
* A tier as declared in `defineChapter`, before it becomes a row.
|
|
6
29
|
*
|
|
@@ -44,7 +67,7 @@ type AdminRecordsCopy = {
|
|
|
44
67
|
[Field in AdminRecordsCopyKey]: string;
|
|
45
68
|
};
|
|
46
69
|
/** Every key a host may override under `admin.records`. */
|
|
47
|
-
type AdminRecordsCopyKey = "workflowMissing" | "invitation" | "comms" | "commsHistory" | "scheduling" | "billing" | "notes" | "access" | "sharing" | "lifecycle" | "role" | "superAdminHint" | "noAccount" | "approve" | "refund" | "approved" | "refunded" | "roleSet" | "messageSent" | "messageNotSent" | "loadingTemplates" | "template" | "chooseTemplate" | "sending" | "send" | "noMessages" | "message" | "newStartPrompt" | "parseFailed" | "cancelConfirm" | "callCancelled" | "callRescheduled" | "noApplication" | "loadingMeetings" | "noMeetings" | "joinMeeting" | "openCalendar" | "reschedule" | "cancel";
|
|
70
|
+
type AdminRecordsCopyKey = "workflowMissing" | "invitation" | "comms" | "commsHistory" | "scheduling" | "billing" | "notes" | "access" | "sharing" | "lifecycle" | "role" | "superAdminHint" | "noAccount" | "approve" | "decline" | "refund" | "approved" | "declined" | "refunded" | "roleSet" | "messageSent" | "messageNotSent" | "loadingTemplates" | "template" | "chooseTemplate" | "sending" | "send" | "noMessages" | "message" | "newStartPrompt" | "parseFailed" | "cancelConfirm" | "callCancelled" | "callRescheduled" | "noApplication" | "loadingMeetings" | "noMeetings" | "joinMeeting" | "openCalendar" | "reschedule" | "cancel";
|
|
48
71
|
|
|
49
72
|
type TextFields<Key extends string> = {
|
|
50
73
|
[Field in Key]: string;
|
|
@@ -1093,6 +1116,12 @@ interface NamedSeatOfferSeat {
|
|
|
1093
1116
|
acceptedAt?: number;
|
|
1094
1117
|
/** When the recipient's own application was approved; the seat is active from then, once the primary is. */
|
|
1095
1118
|
joinedAt?: number;
|
|
1119
|
+
/** True while the invitation waits for the buying member's own approval; nothing has been sent to the recipient yet. */
|
|
1120
|
+
invitationHeld?: true;
|
|
1121
|
+
/** True while the purchaser may still name someone else: the seat is invited or accepted but not yet active. */
|
|
1122
|
+
regiftable?: true;
|
|
1123
|
+
/** When the purchaser last replaced the recipient. */
|
|
1124
|
+
regiftedAt?: number;
|
|
1096
1125
|
}
|
|
1097
1126
|
/** Named-seat offer for the authenticated purchaser, not a transferable gift or arbitrary quantity. */
|
|
1098
1127
|
interface NamedSeatOffer {
|
|
@@ -1135,13 +1164,23 @@ interface NamedSeatInvitation {
|
|
|
1135
1164
|
termEndsAt: number;
|
|
1136
1165
|
}
|
|
1137
1166
|
|
|
1167
|
+
/** Effects a chapter receives over the signed edge; `release_named_recipient` ends a replaced recipient's claim without a refund. */
|
|
1168
|
+
declare const MEMBERSHIP_CHAPTER_EFFECT_KINDS: readonly ["invite_named_recipient", "grant_named_recipient_access", "revoke_named_recipient_access", "release_named_recipient"];
|
|
1169
|
+
/** One of {@link MEMBERSHIP_CHAPTER_EFFECT_KINDS}. */
|
|
1170
|
+
type MembershipChapterEffectKind = (typeof MEMBERSHIP_CHAPTER_EFFECT_KINDS)[number];
|
|
1171
|
+
/** The buying member's invitation may go out: their own Journey approval is durable, not merely paid (BNF bug c3c1d338). */
|
|
1172
|
+
declare const namedSeatInvitationOpen: (member: {
|
|
1173
|
+
status?: unknown;
|
|
1174
|
+
journeyApprovedAt?: unknown;
|
|
1175
|
+
}) => boolean;
|
|
1176
|
+
|
|
1138
1177
|
/** Exact configured chapter/runtime serviced by one scheduled network worker. */
|
|
1139
1178
|
type MembershipEffectScope = Pick<MembershipQuoteTarget, "appId" | "chapterId" | "environment" | "runtime">;
|
|
1140
1179
|
/** Downstream requests carry only identifiers; the signed chapter receiver reads current state and deduplicates by effectId. */
|
|
1141
1180
|
interface MembershipChapterEffect extends MembershipQuoteTarget {
|
|
1142
1181
|
effectId: string;
|
|
1143
1182
|
seatId: string;
|
|
1144
|
-
kind:
|
|
1183
|
+
kind: MembershipChapterEffectKind;
|
|
1145
1184
|
}
|
|
1146
1185
|
/** Recover provider effects from durable state, independently of browser/webhook retries.
|
|
1147
1186
|
* The optional chapter adapter must return a durable, idempotent receipt. An absent adapter leaves work visibly pending.
|
|
@@ -1160,6 +1199,7 @@ declare function drainMembershipEffects(db: ChapterDb, options: {
|
|
|
1160
1199
|
}, now: number): Promise<{
|
|
1161
1200
|
complete: number;
|
|
1162
1201
|
pending: number;
|
|
1202
|
+
held: number;
|
|
1163
1203
|
more: boolean;
|
|
1164
1204
|
}>;
|
|
1165
1205
|
|
|
@@ -1216,6 +1256,15 @@ interface NamedSeatRefundReceipt {
|
|
|
1216
1256
|
refundedCents: number;
|
|
1217
1257
|
subscriptionCanceled: false;
|
|
1218
1258
|
}
|
|
1259
|
+
/** Receipt for naming a different recipient: the seat is invited again, nothing is charged or refunded. */
|
|
1260
|
+
interface NamedSeatRegiftReceipt {
|
|
1261
|
+
seatId: string;
|
|
1262
|
+
status: "pending_acceptance";
|
|
1263
|
+
recipientName: string;
|
|
1264
|
+
recipientEmail: string;
|
|
1265
|
+
regiftedAt: number;
|
|
1266
|
+
releasedRecipientApplicationId: string | null;
|
|
1267
|
+
}
|
|
1219
1268
|
/** Verified purchaser identity and their named recipient, with no caller-selected pricing. */
|
|
1220
1269
|
type NamedSeatCheckoutRequest = MembershipQuoteTarget & {
|
|
1221
1270
|
recipientName: string;
|
|
@@ -1339,6 +1388,12 @@ interface ChapterWorkerOptions {
|
|
|
1339
1388
|
operatorRefund: (input: MembershipQuoteTarget & {
|
|
1340
1389
|
seatId: string;
|
|
1341
1390
|
}, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
|
|
1391
|
+
/** The purchaser (or a super admin) names a different recipient before the seat is active; absent on older adapters. */
|
|
1392
|
+
regift?: (input: MembershipQuoteTarget & {
|
|
1393
|
+
seatId: string;
|
|
1394
|
+
recipientName: string;
|
|
1395
|
+
recipientEmail: string;
|
|
1396
|
+
}, env: ChapterEnv) => Promise<NamedSeatRegiftReceipt>;
|
|
1342
1397
|
};
|
|
1343
1398
|
};
|
|
1344
1399
|
/** Network owner only: operate the membership authority this Worker hosts (seat refunds by a super admin).
|
|
@@ -1425,6 +1480,12 @@ declare function createWorkerContext(options: ChapterWorkerOptions): {
|
|
|
1425
1480
|
operatorRefund: (input: MembershipQuoteTarget & {
|
|
1426
1481
|
seatId: string;
|
|
1427
1482
|
}, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
|
|
1483
|
+
/** The purchaser (or a super admin) names a different recipient before the seat is active; absent on older adapters. */
|
|
1484
|
+
regift?: (input: MembershipQuoteTarget & {
|
|
1485
|
+
seatId: string;
|
|
1486
|
+
recipientName: string;
|
|
1487
|
+
recipientEmail: string;
|
|
1488
|
+
}, env: ChapterEnv) => Promise<NamedSeatRegiftReceipt>;
|
|
1428
1489
|
};
|
|
1429
1490
|
} | undefined;
|
|
1430
1491
|
membershipAuthorityOperator: {
|
|
@@ -1503,6 +1564,91 @@ type NamedSeatOperatorRefundInput = MembershipQuoteTarget & {
|
|
|
1503
1564
|
*/
|
|
1504
1565
|
declare function refundNamedSeatByOperator(db: ChapterDb, input: NamedSeatOperatorRefundInput, stripeSecretKey: string, now: number): Promise<NamedSeatRefundReceipt>;
|
|
1505
1566
|
|
|
1567
|
+
/** Seat states in which the purchaser may still name someone else: invited or accepted, never active, refunded or unpaid. */
|
|
1568
|
+
declare const REGIFTABLE_SEAT_STATUSES: readonly ["pending_acceptance", "pending_approval", "pending_primary"];
|
|
1569
|
+
/** Whether a seat may be given to a different recipient (BNF bug 38000934): final once active. */
|
|
1570
|
+
declare const namedSeatRegiftable: (seat: {
|
|
1571
|
+
status?: unknown;
|
|
1572
|
+
}) => boolean;
|
|
1573
|
+
/** The purchaser's exact seat and the person who should hold it from now on. */
|
|
1574
|
+
type RegiftNamedSeatInput = MembershipQuoteTarget & {
|
|
1575
|
+
seatId: string;
|
|
1576
|
+
recipientName: string;
|
|
1577
|
+
recipientEmail: string;
|
|
1578
|
+
};
|
|
1579
|
+
/** One prior holder of a seat, kept on the seat as history after the purchaser named someone else. */
|
|
1580
|
+
interface FormerNamedSeatRecipient {
|
|
1581
|
+
recipientName: string;
|
|
1582
|
+
recipientEmail: string;
|
|
1583
|
+
recipientClaimId: string;
|
|
1584
|
+
releasedAt: number;
|
|
1585
|
+
recipientUserId?: string;
|
|
1586
|
+
recipientApplicationId?: string;
|
|
1587
|
+
acceptedAt?: number;
|
|
1588
|
+
journeyApprovedAt?: number;
|
|
1589
|
+
}
|
|
1590
|
+
/** Give an invited or accepted seat to a different named person, before it is active.
|
|
1591
|
+
* The old invitation link stops resolving (the seat no longer names that email), the entitlement goes back to
|
|
1592
|
+
* pending acceptance, a new invitation effect is queued, and a former recipient who had accepted gets a
|
|
1593
|
+
* `release_named_recipient` effect so the chapter closes their application. Money is untouched: the seat's
|
|
1594
|
+
* payment and renewal line stay exactly as they were, which is what makes this work for an included seat too.
|
|
1595
|
+
* The former recipient is kept on the seat's `formerRecipients` history. Replays with the same person converge.
|
|
1596
|
+
*/
|
|
1597
|
+
declare function regiftNamedSeat(db: ChapterDb, input: RegiftNamedSeatInput, now: number): Promise<NamedSeatRegiftReceipt>;
|
|
1598
|
+
|
|
1599
|
+
/** Who may keep the seat: the exact application the authority still names, or whoever holds the new recipient email. */
|
|
1600
|
+
interface NamedSeatReleaseInput {
|
|
1601
|
+
seatId: string;
|
|
1602
|
+
recipientApplicationId?: string | null;
|
|
1603
|
+
recipientUserId?: string | null;
|
|
1604
|
+
keepRecipientEmail?: string;
|
|
1605
|
+
}
|
|
1606
|
+
/** Close the applications of recipients a seat no longer names (BNF bug 38000934).
|
|
1607
|
+
* The replaced person keeps their application and history: it moves to `declined`, is marked closed, and loses
|
|
1608
|
+
* its seat binding so the new recipient can claim the same seat. Nothing is refunded, because the seat itself
|
|
1609
|
+
* was not returned; a role that approval promoted is taken back. Idempotent: an application already released
|
|
1610
|
+
* is left alone, and a bound recipient the effect names is released even if the chapter already did it.
|
|
1611
|
+
*/
|
|
1612
|
+
declare function releaseNamedSeatRecipientApplications(db: ChapterDb, env: ChapterEnv, ctx: WorkerContext, input: NamedSeatReleaseInput): Promise<{
|
|
1613
|
+
released: string[];
|
|
1614
|
+
}>;
|
|
1615
|
+
|
|
1616
|
+
type Row$3 = Record<string, unknown>;
|
|
1617
|
+
/** Whether an application's status can still be refused outright: payment held means a refund, not a decline. */
|
|
1618
|
+
declare const DECLINABLE_FROM: (status: string) => boolean;
|
|
1619
|
+
/** Refuse an applicant who holds no payment (BNF bug fa96b11c): a free-tier applicant, or a paid-tier applicant who never paid.
|
|
1620
|
+
* The application closes as `declined`, the CRM stage follows, and no email is sent; the operator says it in person.
|
|
1621
|
+
* A paid applicant is never declined here: the refund operation is the only way to end a paid membership. A gifted
|
|
1622
|
+
* seat's recipient is released by the purchaser naming someone else, or refunded. Replays converge on the declined row. */
|
|
1623
|
+
declare function declineApplication(db: ChapterDb, env: ChapterEnv, ctx: WorkerContext, app: Row$3): Promise<Response>;
|
|
1624
|
+
|
|
1625
|
+
type Row$2 = Record<string, unknown>;
|
|
1626
|
+
/** "Not a paid fit" (BNF bug f7bc92ee): after a full refund, keep the person on a free tier of the same chapter with member access.
|
|
1627
|
+
* The refunded purchase is archived as checkout history and its billing fields leave the row; the application moves to the
|
|
1628
|
+
* last approvable stage on the free tier and is approved at once through the ordinary approval, which promotes the account
|
|
1629
|
+
* and sends the welcome notice. Safe to repeat: a conversion that already happened is only re-approved. */
|
|
1630
|
+
declare function continueApplicationOnFreeTier(db: ChapterDb, env: ChapterEnv, ctx: WorkerContext, app: Row$2, tier: ChapterTier, origin: string): Promise<Response>;
|
|
1631
|
+
|
|
1632
|
+
type Row$1 = Record<string, unknown>;
|
|
1633
|
+
/** An application that ended without approval still holding: declined, refunded, canceled, or closed by a refund flag.
|
|
1634
|
+
* Such a person may apply again (BNF bug 79590edc); the closed row stays as history. */
|
|
1635
|
+
declare const closedApplication: (row: Row$1) => boolean;
|
|
1636
|
+
/** The closed application a new attempt continues from: its account binding carries over, its unique signup key is released. */
|
|
1637
|
+
interface SignupPredecessor {
|
|
1638
|
+
id: string;
|
|
1639
|
+
clerkUserId?: string;
|
|
1640
|
+
}
|
|
1641
|
+
/** Either a conflict response, or permission to write, with the predecessor a returning applicant adopts. */
|
|
1642
|
+
interface SignupEligibility {
|
|
1643
|
+
conflict: Response | null;
|
|
1644
|
+
predecessor: SignupPredecessor | null;
|
|
1645
|
+
}
|
|
1646
|
+
/** Refuse known accounts before persisting any application, consent or CRM data.
|
|
1647
|
+
* Provider failures are unavailable, never evidence that an address is free. A person whose every earlier application
|
|
1648
|
+
* in this chapter is closed may apply again: the newest closed row (and the account bound to it) becomes the predecessor.
|
|
1649
|
+
*/
|
|
1650
|
+
declare function resolveSignupEligibility(db: ChapterDb, chapter: Chapter, fields: Record<string, unknown>, submissionId?: string): Promise<SignupEligibility>;
|
|
1651
|
+
|
|
1506
1652
|
/** Why one membership was left as it was. `would_not_widen` is the only-widens rule: the version would raise the renewal. */
|
|
1507
1653
|
type MembershipRetermSkipReason = "not_found" | "scope_mismatch" | "status" | "not_founding" | "cohort_mismatch" | "sku_not_discounted" | "would_not_widen" | "provider_mismatch";
|
|
1508
1654
|
/** What a re-term run did, member by member. Everything a super admin needs to read back is here; nothing is inferred later. */
|
|
@@ -2189,4 +2335,4 @@ declare function chapterWorker(options: ChapterWorkerOptions): {
|
|
|
2189
2335
|
fetch(req: Request, env: ChapterEnv): Promise<Response>;
|
|
2190
2336
|
};
|
|
2191
2337
|
|
|
2192
|
-
export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, AdmissionGrantDeliveryError, type AdmissionGrantDeliveryOptions, type BuilderLibraryDeliveryOptions, type ChapterEnv, type ChapterErrorRecorder, type ChapterErrorReport, type ChapterWorkerOptions, type IncludedNamedSeatReceipt, type LeaderAdmissionAssignment, type LeaderAdmissionDelivery, type LeaderAdmissionDeliveryStatus, MEMBERSHIP_AUTHORITY_PATH, type MemberContentDeliveryOptions, type MembershipAuthorityHandlerOptions, type MembershipAuthorityPeer, type MembershipChapterEffect, type MembershipEffectScope, type MembershipRetermInput, type MembershipRetermReceipt, type MembershipRetermSkipReason, type MembershipWorkerAdapter, type MembershipWorkerAdapterOptions, type NamedSeatOffer, type NamedSeatOfferSeat, type NamedSeatOperatorRefundInput, type NamedSeatRecipientState, type NamedSeatRefundReason, type NetworkTargetTransport, NetworkTargetTransportError, type Route, type SeatRepriceReceipt, type SeatRepriceScope, type SignupControlDeliveryOptions, type WorkerContext, chapterMembershipAccess, chapterWorker, createMembershipAuthorityHandler, createMembershipAuthorityStorage, createMembershipChapterEffectRoute, createMembershipWorkerAdapter, createWorkerContext, deliverAdmissionGrants, deliverBuilderLibrary, deliverMemberContent, deliverMembershipChapterEffect, deliverSignupControl, drainMembershipEffects, grantIncludedNamedSeat, liftSeatPurchaseWindow, lowerSeatPrice, namedSeatIncluded, namedSeatRecipientState, readNamedSeatOffer, refundNamedSeatByOperator, renderActiveSignupControlHtml, resolveNetworkTargetTransport, retermMembershipDiscount, retryChapterApprovalEffects, retryLeaderAdmissionDeliveries, withActiveSignupControlTheme };
|
|
2338
|
+
export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, AdmissionGrantDeliveryError, type AdmissionGrantDeliveryOptions, type BuilderLibraryDeliveryOptions, type ChapterEnv, type ChapterErrorRecorder, type ChapterErrorReport, type ChapterWorkerOptions, DECLINABLE_FROM, type FormerNamedSeatRecipient, type IncludedNamedSeatReceipt, type LeaderAdmissionAssignment, type LeaderAdmissionDelivery, type LeaderAdmissionDeliveryStatus, MEMBERSHIP_AUTHORITY_PATH, MEMBERSHIP_CHAPTER_EFFECT_KINDS, type MemberContentDeliveryOptions, type MembershipAuthorityHandlerOptions, type MembershipAuthorityPeer, type MembershipChapterEffect, type MembershipChapterEffectKind, type MembershipEffectScope, type MembershipRetermInput, type MembershipRetermReceipt, type MembershipRetermSkipReason, type MembershipWorkerAdapter, type MembershipWorkerAdapterOptions, type NamedSeatOffer, type NamedSeatOfferSeat, type NamedSeatOperatorRefundInput, type NamedSeatRecipientState, type NamedSeatRefundReason, type NamedSeatRegiftReceipt, type NamedSeatReleaseInput, type NetworkTargetTransport, NetworkTargetTransportError, REGIFTABLE_SEAT_STATUSES, type RegiftNamedSeatInput, type Route, type SeatRepriceReceipt, type SeatRepriceScope, type SignupControlDeliveryOptions, type SignupEligibility, type SignupPredecessor, type WorkerContext, chapterMembershipAccess, chapterWorker, closedApplication, continueApplicationOnFreeTier, createMembershipAuthorityHandler, createMembershipAuthorityStorage, createMembershipChapterEffectRoute, createMembershipWorkerAdapter, createWorkerContext, declineApplication, deliverAdmissionGrants, deliverBuilderLibrary, deliverMemberContent, deliverMembershipChapterEffect, deliverSignupControl, drainMembershipEffects, grantIncludedNamedSeat, liftSeatPurchaseWindow, lowerSeatPrice, namedSeatIncluded, namedSeatInvitationOpen, namedSeatRecipientState, namedSeatRegiftable, readNamedSeatOffer, refundNamedSeatByOperator, regiftNamedSeat, releaseNamedSeatRecipientApplications, renderActiveSignupControlHtml, resolveNetworkTargetTransport, resolveSignupEligibility, retermMembershipDiscount, retryChapterApprovalEffects, retryLeaderAdmissionDeliveries, withActiveSignupControlTheme };
|
package/dist/worker/index.d.ts
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
import { CrmConfig, Crm, FieldConditions } from '@odla-ai/crm';
|
|
2
2
|
import { initAdmin } from '@odla-ai/db';
|
|
3
3
|
|
|
4
|
+
/** One membership tier a chapter offers. `priceCents: 0` means free. */
|
|
5
|
+
interface ChapterTier {
|
|
6
|
+
/** Stable slug, referenced by `applications.tierId`. Never renumbered. */
|
|
7
|
+
id: string;
|
|
8
|
+
/** The group this tier belongs to. */
|
|
9
|
+
groupId: string;
|
|
10
|
+
/** Display name, e.g. "Founding". */
|
|
11
|
+
name: string;
|
|
12
|
+
/** Price in minor units. `0` is free and needs no Stripe price. */
|
|
13
|
+
priceCents: number;
|
|
14
|
+
/** ISO currency inherited from the group for legacy rows. */
|
|
15
|
+
currency?: string;
|
|
16
|
+
/** Recurring interval inherited from the group for legacy rows. */
|
|
17
|
+
interval?: "year" | "month";
|
|
18
|
+
/** Stripe price to subscribe. Required only when `priceCents > 0`. */
|
|
19
|
+
stripePriceId?: string | null;
|
|
20
|
+
/** Short description shown beside the tier on the join page. */
|
|
21
|
+
blurb?: string;
|
|
22
|
+
/** Ascending display order; ties fall back to `id` for a stable sort. */
|
|
23
|
+
sortOrder: number;
|
|
24
|
+
/** An inactive tier is retained for existing members but never offered. */
|
|
25
|
+
active: boolean;
|
|
26
|
+
}
|
|
4
27
|
/**
|
|
5
28
|
* A tier as declared in `defineChapter`, before it becomes a row.
|
|
6
29
|
*
|
|
@@ -44,7 +67,7 @@ type AdminRecordsCopy = {
|
|
|
44
67
|
[Field in AdminRecordsCopyKey]: string;
|
|
45
68
|
};
|
|
46
69
|
/** Every key a host may override under `admin.records`. */
|
|
47
|
-
type AdminRecordsCopyKey = "workflowMissing" | "invitation" | "comms" | "commsHistory" | "scheduling" | "billing" | "notes" | "access" | "sharing" | "lifecycle" | "role" | "superAdminHint" | "noAccount" | "approve" | "refund" | "approved" | "refunded" | "roleSet" | "messageSent" | "messageNotSent" | "loadingTemplates" | "template" | "chooseTemplate" | "sending" | "send" | "noMessages" | "message" | "newStartPrompt" | "parseFailed" | "cancelConfirm" | "callCancelled" | "callRescheduled" | "noApplication" | "loadingMeetings" | "noMeetings" | "joinMeeting" | "openCalendar" | "reschedule" | "cancel";
|
|
70
|
+
type AdminRecordsCopyKey = "workflowMissing" | "invitation" | "comms" | "commsHistory" | "scheduling" | "billing" | "notes" | "access" | "sharing" | "lifecycle" | "role" | "superAdminHint" | "noAccount" | "approve" | "decline" | "refund" | "approved" | "declined" | "refunded" | "roleSet" | "messageSent" | "messageNotSent" | "loadingTemplates" | "template" | "chooseTemplate" | "sending" | "send" | "noMessages" | "message" | "newStartPrompt" | "parseFailed" | "cancelConfirm" | "callCancelled" | "callRescheduled" | "noApplication" | "loadingMeetings" | "noMeetings" | "joinMeeting" | "openCalendar" | "reschedule" | "cancel";
|
|
48
71
|
|
|
49
72
|
type TextFields<Key extends string> = {
|
|
50
73
|
[Field in Key]: string;
|
|
@@ -1093,6 +1116,12 @@ interface NamedSeatOfferSeat {
|
|
|
1093
1116
|
acceptedAt?: number;
|
|
1094
1117
|
/** When the recipient's own application was approved; the seat is active from then, once the primary is. */
|
|
1095
1118
|
joinedAt?: number;
|
|
1119
|
+
/** True while the invitation waits for the buying member's own approval; nothing has been sent to the recipient yet. */
|
|
1120
|
+
invitationHeld?: true;
|
|
1121
|
+
/** True while the purchaser may still name someone else: the seat is invited or accepted but not yet active. */
|
|
1122
|
+
regiftable?: true;
|
|
1123
|
+
/** When the purchaser last replaced the recipient. */
|
|
1124
|
+
regiftedAt?: number;
|
|
1096
1125
|
}
|
|
1097
1126
|
/** Named-seat offer for the authenticated purchaser, not a transferable gift or arbitrary quantity. */
|
|
1098
1127
|
interface NamedSeatOffer {
|
|
@@ -1135,13 +1164,23 @@ interface NamedSeatInvitation {
|
|
|
1135
1164
|
termEndsAt: number;
|
|
1136
1165
|
}
|
|
1137
1166
|
|
|
1167
|
+
/** Effects a chapter receives over the signed edge; `release_named_recipient` ends a replaced recipient's claim without a refund. */
|
|
1168
|
+
declare const MEMBERSHIP_CHAPTER_EFFECT_KINDS: readonly ["invite_named_recipient", "grant_named_recipient_access", "revoke_named_recipient_access", "release_named_recipient"];
|
|
1169
|
+
/** One of {@link MEMBERSHIP_CHAPTER_EFFECT_KINDS}. */
|
|
1170
|
+
type MembershipChapterEffectKind = (typeof MEMBERSHIP_CHAPTER_EFFECT_KINDS)[number];
|
|
1171
|
+
/** The buying member's invitation may go out: their own Journey approval is durable, not merely paid (BNF bug c3c1d338). */
|
|
1172
|
+
declare const namedSeatInvitationOpen: (member: {
|
|
1173
|
+
status?: unknown;
|
|
1174
|
+
journeyApprovedAt?: unknown;
|
|
1175
|
+
}) => boolean;
|
|
1176
|
+
|
|
1138
1177
|
/** Exact configured chapter/runtime serviced by one scheduled network worker. */
|
|
1139
1178
|
type MembershipEffectScope = Pick<MembershipQuoteTarget, "appId" | "chapterId" | "environment" | "runtime">;
|
|
1140
1179
|
/** Downstream requests carry only identifiers; the signed chapter receiver reads current state and deduplicates by effectId. */
|
|
1141
1180
|
interface MembershipChapterEffect extends MembershipQuoteTarget {
|
|
1142
1181
|
effectId: string;
|
|
1143
1182
|
seatId: string;
|
|
1144
|
-
kind:
|
|
1183
|
+
kind: MembershipChapterEffectKind;
|
|
1145
1184
|
}
|
|
1146
1185
|
/** Recover provider effects from durable state, independently of browser/webhook retries.
|
|
1147
1186
|
* The optional chapter adapter must return a durable, idempotent receipt. An absent adapter leaves work visibly pending.
|
|
@@ -1160,6 +1199,7 @@ declare function drainMembershipEffects(db: ChapterDb, options: {
|
|
|
1160
1199
|
}, now: number): Promise<{
|
|
1161
1200
|
complete: number;
|
|
1162
1201
|
pending: number;
|
|
1202
|
+
held: number;
|
|
1163
1203
|
more: boolean;
|
|
1164
1204
|
}>;
|
|
1165
1205
|
|
|
@@ -1216,6 +1256,15 @@ interface NamedSeatRefundReceipt {
|
|
|
1216
1256
|
refundedCents: number;
|
|
1217
1257
|
subscriptionCanceled: false;
|
|
1218
1258
|
}
|
|
1259
|
+
/** Receipt for naming a different recipient: the seat is invited again, nothing is charged or refunded. */
|
|
1260
|
+
interface NamedSeatRegiftReceipt {
|
|
1261
|
+
seatId: string;
|
|
1262
|
+
status: "pending_acceptance";
|
|
1263
|
+
recipientName: string;
|
|
1264
|
+
recipientEmail: string;
|
|
1265
|
+
regiftedAt: number;
|
|
1266
|
+
releasedRecipientApplicationId: string | null;
|
|
1267
|
+
}
|
|
1219
1268
|
/** Verified purchaser identity and their named recipient, with no caller-selected pricing. */
|
|
1220
1269
|
type NamedSeatCheckoutRequest = MembershipQuoteTarget & {
|
|
1221
1270
|
recipientName: string;
|
|
@@ -1339,6 +1388,12 @@ interface ChapterWorkerOptions {
|
|
|
1339
1388
|
operatorRefund: (input: MembershipQuoteTarget & {
|
|
1340
1389
|
seatId: string;
|
|
1341
1390
|
}, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
|
|
1391
|
+
/** The purchaser (or a super admin) names a different recipient before the seat is active; absent on older adapters. */
|
|
1392
|
+
regift?: (input: MembershipQuoteTarget & {
|
|
1393
|
+
seatId: string;
|
|
1394
|
+
recipientName: string;
|
|
1395
|
+
recipientEmail: string;
|
|
1396
|
+
}, env: ChapterEnv) => Promise<NamedSeatRegiftReceipt>;
|
|
1342
1397
|
};
|
|
1343
1398
|
};
|
|
1344
1399
|
/** Network owner only: operate the membership authority this Worker hosts (seat refunds by a super admin).
|
|
@@ -1425,6 +1480,12 @@ declare function createWorkerContext(options: ChapterWorkerOptions): {
|
|
|
1425
1480
|
operatorRefund: (input: MembershipQuoteTarget & {
|
|
1426
1481
|
seatId: string;
|
|
1427
1482
|
}, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
|
|
1483
|
+
/** The purchaser (or a super admin) names a different recipient before the seat is active; absent on older adapters. */
|
|
1484
|
+
regift?: (input: MembershipQuoteTarget & {
|
|
1485
|
+
seatId: string;
|
|
1486
|
+
recipientName: string;
|
|
1487
|
+
recipientEmail: string;
|
|
1488
|
+
}, env: ChapterEnv) => Promise<NamedSeatRegiftReceipt>;
|
|
1428
1489
|
};
|
|
1429
1490
|
} | undefined;
|
|
1430
1491
|
membershipAuthorityOperator: {
|
|
@@ -1503,6 +1564,91 @@ type NamedSeatOperatorRefundInput = MembershipQuoteTarget & {
|
|
|
1503
1564
|
*/
|
|
1504
1565
|
declare function refundNamedSeatByOperator(db: ChapterDb, input: NamedSeatOperatorRefundInput, stripeSecretKey: string, now: number): Promise<NamedSeatRefundReceipt>;
|
|
1505
1566
|
|
|
1567
|
+
/** Seat states in which the purchaser may still name someone else: invited or accepted, never active, refunded or unpaid. */
|
|
1568
|
+
declare const REGIFTABLE_SEAT_STATUSES: readonly ["pending_acceptance", "pending_approval", "pending_primary"];
|
|
1569
|
+
/** Whether a seat may be given to a different recipient (BNF bug 38000934): final once active. */
|
|
1570
|
+
declare const namedSeatRegiftable: (seat: {
|
|
1571
|
+
status?: unknown;
|
|
1572
|
+
}) => boolean;
|
|
1573
|
+
/** The purchaser's exact seat and the person who should hold it from now on. */
|
|
1574
|
+
type RegiftNamedSeatInput = MembershipQuoteTarget & {
|
|
1575
|
+
seatId: string;
|
|
1576
|
+
recipientName: string;
|
|
1577
|
+
recipientEmail: string;
|
|
1578
|
+
};
|
|
1579
|
+
/** One prior holder of a seat, kept on the seat as history after the purchaser named someone else. */
|
|
1580
|
+
interface FormerNamedSeatRecipient {
|
|
1581
|
+
recipientName: string;
|
|
1582
|
+
recipientEmail: string;
|
|
1583
|
+
recipientClaimId: string;
|
|
1584
|
+
releasedAt: number;
|
|
1585
|
+
recipientUserId?: string;
|
|
1586
|
+
recipientApplicationId?: string;
|
|
1587
|
+
acceptedAt?: number;
|
|
1588
|
+
journeyApprovedAt?: number;
|
|
1589
|
+
}
|
|
1590
|
+
/** Give an invited or accepted seat to a different named person, before it is active.
|
|
1591
|
+
* The old invitation link stops resolving (the seat no longer names that email), the entitlement goes back to
|
|
1592
|
+
* pending acceptance, a new invitation effect is queued, and a former recipient who had accepted gets a
|
|
1593
|
+
* `release_named_recipient` effect so the chapter closes their application. Money is untouched: the seat's
|
|
1594
|
+
* payment and renewal line stay exactly as they were, which is what makes this work for an included seat too.
|
|
1595
|
+
* The former recipient is kept on the seat's `formerRecipients` history. Replays with the same person converge.
|
|
1596
|
+
*/
|
|
1597
|
+
declare function regiftNamedSeat(db: ChapterDb, input: RegiftNamedSeatInput, now: number): Promise<NamedSeatRegiftReceipt>;
|
|
1598
|
+
|
|
1599
|
+
/** Who may keep the seat: the exact application the authority still names, or whoever holds the new recipient email. */
|
|
1600
|
+
interface NamedSeatReleaseInput {
|
|
1601
|
+
seatId: string;
|
|
1602
|
+
recipientApplicationId?: string | null;
|
|
1603
|
+
recipientUserId?: string | null;
|
|
1604
|
+
keepRecipientEmail?: string;
|
|
1605
|
+
}
|
|
1606
|
+
/** Close the applications of recipients a seat no longer names (BNF bug 38000934).
|
|
1607
|
+
* The replaced person keeps their application and history: it moves to `declined`, is marked closed, and loses
|
|
1608
|
+
* its seat binding so the new recipient can claim the same seat. Nothing is refunded, because the seat itself
|
|
1609
|
+
* was not returned; a role that approval promoted is taken back. Idempotent: an application already released
|
|
1610
|
+
* is left alone, and a bound recipient the effect names is released even if the chapter already did it.
|
|
1611
|
+
*/
|
|
1612
|
+
declare function releaseNamedSeatRecipientApplications(db: ChapterDb, env: ChapterEnv, ctx: WorkerContext, input: NamedSeatReleaseInput): Promise<{
|
|
1613
|
+
released: string[];
|
|
1614
|
+
}>;
|
|
1615
|
+
|
|
1616
|
+
type Row$3 = Record<string, unknown>;
|
|
1617
|
+
/** Whether an application's status can still be refused outright: payment held means a refund, not a decline. */
|
|
1618
|
+
declare const DECLINABLE_FROM: (status: string) => boolean;
|
|
1619
|
+
/** Refuse an applicant who holds no payment (BNF bug fa96b11c): a free-tier applicant, or a paid-tier applicant who never paid.
|
|
1620
|
+
* The application closes as `declined`, the CRM stage follows, and no email is sent; the operator says it in person.
|
|
1621
|
+
* A paid applicant is never declined here: the refund operation is the only way to end a paid membership. A gifted
|
|
1622
|
+
* seat's recipient is released by the purchaser naming someone else, or refunded. Replays converge on the declined row. */
|
|
1623
|
+
declare function declineApplication(db: ChapterDb, env: ChapterEnv, ctx: WorkerContext, app: Row$3): Promise<Response>;
|
|
1624
|
+
|
|
1625
|
+
type Row$2 = Record<string, unknown>;
|
|
1626
|
+
/** "Not a paid fit" (BNF bug f7bc92ee): after a full refund, keep the person on a free tier of the same chapter with member access.
|
|
1627
|
+
* The refunded purchase is archived as checkout history and its billing fields leave the row; the application moves to the
|
|
1628
|
+
* last approvable stage on the free tier and is approved at once through the ordinary approval, which promotes the account
|
|
1629
|
+
* and sends the welcome notice. Safe to repeat: a conversion that already happened is only re-approved. */
|
|
1630
|
+
declare function continueApplicationOnFreeTier(db: ChapterDb, env: ChapterEnv, ctx: WorkerContext, app: Row$2, tier: ChapterTier, origin: string): Promise<Response>;
|
|
1631
|
+
|
|
1632
|
+
type Row$1 = Record<string, unknown>;
|
|
1633
|
+
/** An application that ended without approval still holding: declined, refunded, canceled, or closed by a refund flag.
|
|
1634
|
+
* Such a person may apply again (BNF bug 79590edc); the closed row stays as history. */
|
|
1635
|
+
declare const closedApplication: (row: Row$1) => boolean;
|
|
1636
|
+
/** The closed application a new attempt continues from: its account binding carries over, its unique signup key is released. */
|
|
1637
|
+
interface SignupPredecessor {
|
|
1638
|
+
id: string;
|
|
1639
|
+
clerkUserId?: string;
|
|
1640
|
+
}
|
|
1641
|
+
/** Either a conflict response, or permission to write, with the predecessor a returning applicant adopts. */
|
|
1642
|
+
interface SignupEligibility {
|
|
1643
|
+
conflict: Response | null;
|
|
1644
|
+
predecessor: SignupPredecessor | null;
|
|
1645
|
+
}
|
|
1646
|
+
/** Refuse known accounts before persisting any application, consent or CRM data.
|
|
1647
|
+
* Provider failures are unavailable, never evidence that an address is free. A person whose every earlier application
|
|
1648
|
+
* in this chapter is closed may apply again: the newest closed row (and the account bound to it) becomes the predecessor.
|
|
1649
|
+
*/
|
|
1650
|
+
declare function resolveSignupEligibility(db: ChapterDb, chapter: Chapter, fields: Record<string, unknown>, submissionId?: string): Promise<SignupEligibility>;
|
|
1651
|
+
|
|
1506
1652
|
/** Why one membership was left as it was. `would_not_widen` is the only-widens rule: the version would raise the renewal. */
|
|
1507
1653
|
type MembershipRetermSkipReason = "not_found" | "scope_mismatch" | "status" | "not_founding" | "cohort_mismatch" | "sku_not_discounted" | "would_not_widen" | "provider_mismatch";
|
|
1508
1654
|
/** What a re-term run did, member by member. Everything a super admin needs to read back is here; nothing is inferred later. */
|
|
@@ -2189,4 +2335,4 @@ declare function chapterWorker(options: ChapterWorkerOptions): {
|
|
|
2189
2335
|
fetch(req: Request, env: ChapterEnv): Promise<Response>;
|
|
2190
2336
|
};
|
|
2191
2337
|
|
|
2192
|
-
export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, AdmissionGrantDeliveryError, type AdmissionGrantDeliveryOptions, type BuilderLibraryDeliveryOptions, type ChapterEnv, type ChapterErrorRecorder, type ChapterErrorReport, type ChapterWorkerOptions, type IncludedNamedSeatReceipt, type LeaderAdmissionAssignment, type LeaderAdmissionDelivery, type LeaderAdmissionDeliveryStatus, MEMBERSHIP_AUTHORITY_PATH, type MemberContentDeliveryOptions, type MembershipAuthorityHandlerOptions, type MembershipAuthorityPeer, type MembershipChapterEffect, type MembershipEffectScope, type MembershipRetermInput, type MembershipRetermReceipt, type MembershipRetermSkipReason, type MembershipWorkerAdapter, type MembershipWorkerAdapterOptions, type NamedSeatOffer, type NamedSeatOfferSeat, type NamedSeatOperatorRefundInput, type NamedSeatRecipientState, type NamedSeatRefundReason, type NetworkTargetTransport, NetworkTargetTransportError, type Route, type SeatRepriceReceipt, type SeatRepriceScope, type SignupControlDeliveryOptions, type WorkerContext, chapterMembershipAccess, chapterWorker, createMembershipAuthorityHandler, createMembershipAuthorityStorage, createMembershipChapterEffectRoute, createMembershipWorkerAdapter, createWorkerContext, deliverAdmissionGrants, deliverBuilderLibrary, deliverMemberContent, deliverMembershipChapterEffect, deliverSignupControl, drainMembershipEffects, grantIncludedNamedSeat, liftSeatPurchaseWindow, lowerSeatPrice, namedSeatIncluded, namedSeatRecipientState, readNamedSeatOffer, refundNamedSeatByOperator, renderActiveSignupControlHtml, resolveNetworkTargetTransport, retermMembershipDiscount, retryChapterApprovalEffects, retryLeaderAdmissionDeliveries, withActiveSignupControlTheme };
|
|
2338
|
+
export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, AdmissionGrantDeliveryError, type AdmissionGrantDeliveryOptions, type BuilderLibraryDeliveryOptions, type ChapterEnv, type ChapterErrorRecorder, type ChapterErrorReport, type ChapterWorkerOptions, DECLINABLE_FROM, type FormerNamedSeatRecipient, type IncludedNamedSeatReceipt, type LeaderAdmissionAssignment, type LeaderAdmissionDelivery, type LeaderAdmissionDeliveryStatus, MEMBERSHIP_AUTHORITY_PATH, MEMBERSHIP_CHAPTER_EFFECT_KINDS, type MemberContentDeliveryOptions, type MembershipAuthorityHandlerOptions, type MembershipAuthorityPeer, type MembershipChapterEffect, type MembershipChapterEffectKind, type MembershipEffectScope, type MembershipRetermInput, type MembershipRetermReceipt, type MembershipRetermSkipReason, type MembershipWorkerAdapter, type MembershipWorkerAdapterOptions, type NamedSeatOffer, type NamedSeatOfferSeat, type NamedSeatOperatorRefundInput, type NamedSeatRecipientState, type NamedSeatRefundReason, type NamedSeatRegiftReceipt, type NamedSeatReleaseInput, type NetworkTargetTransport, NetworkTargetTransportError, REGIFTABLE_SEAT_STATUSES, type RegiftNamedSeatInput, type Route, type SeatRepriceReceipt, type SeatRepriceScope, type SignupControlDeliveryOptions, type SignupEligibility, type SignupPredecessor, type WorkerContext, chapterMembershipAccess, chapterWorker, closedApplication, continueApplicationOnFreeTier, createMembershipAuthorityHandler, createMembershipAuthorityStorage, createMembershipChapterEffectRoute, createMembershipWorkerAdapter, createWorkerContext, declineApplication, deliverAdmissionGrants, deliverBuilderLibrary, deliverMemberContent, deliverMembershipChapterEffect, deliverSignupControl, drainMembershipEffects, grantIncludedNamedSeat, liftSeatPurchaseWindow, lowerSeatPrice, namedSeatIncluded, namedSeatInvitationOpen, namedSeatRecipientState, namedSeatRegiftable, readNamedSeatOffer, refundNamedSeatByOperator, regiftNamedSeat, releaseNamedSeatRecipientApplications, renderActiveSignupControlHtml, resolveNetworkTargetTransport, resolveSignupEligibility, retermMembershipDiscount, retryChapterApprovalEffects, retryLeaderAdmissionDeliveries, withActiveSignupControlTheme };
|