@odla-ai/chapter 0.49.0 → 0.50.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.
@@ -27,9 +27,17 @@ type TextFields$1<Key extends string> = {
27
27
  /** User-visible language for sharing, delivery state, and leader rollups. */
28
28
  type AdminNetworkCopy = TextFields$1<"title" | "allowlistDescription" | "sharing" | "shareWith" | "shared" | "shareFailed" | "deliveryFailed" | "loadingRollup" | "loadRollupFailed" | "overview" | "configuredFollowers" | "reachableFollowers" | "recordsAcrossFollowers" | "noFollowers" | "followers" | "available" | "unavailable" | "transportReachable" | "transportUnavailable" | "transportNotChecked" | "bindingTransport" | "urlTransport" | "activeConfiguration" | "noActiveConfiguration" | "publicSiteAvailable" | "publicSiteUnavailable" | "publicSiteNotChecked" | "recordTotals" | "noRecordTotals">;
29
29
 
30
+ /** Copy for the person record panels: lifecycle actions, comms, scheduling, billing and meetings. */
31
+ type AdminRecordsCopy = {
32
+ [Field in AdminRecordsCopyKey]: string;
33
+ };
34
+ /** Every key a host may override under `admin.records`. */
35
+ 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";
36
+
30
37
  type TextFields<Key extends string> = {
31
38
  [Field in Key]: string;
32
39
  };
40
+
33
41
  /** Complete serializable language for Chapter surfaces; use render slots for markup and `formatChapterCopy()` for placeholders. */
34
42
  interface ChapterCopy {
35
43
  common: TextFields<"loading" | "saved" | "unknown">;
@@ -48,7 +56,7 @@ interface ChapterCopy {
48
56
  * agree rather than merely restating the policy. Set it to an empty string
49
57
  * to render the checkbox with the policy as its only label.
50
58
  */
51
- payment: TextFields<"setupFailed" | "preparing" | "pending" | "processing" | "payAndContinue" | "incomplete" | "consent">;
59
+ payment: TextFields<"setupFailed" | "preparing" | "pending" | "processing" | "payAndContinue" | "incomplete" | "consent" | "foundingMember" | "foundingDiscount">;
52
60
  done: TextFields<"label" | "calendarInvite" | "memberArea">;
53
61
  accepted: TextFields<"label" | "body">;
54
62
  gift: TextFields<"chooseSelf" | "optionsLabel" | "label" | "body" | "save" | "rotate" | "rotateFailed" | "claimTitle" | "claimBody" | "code" | "redeem" | "redeemed" | "redeemFailed">;
@@ -74,7 +82,7 @@ interface ChapterCopy {
74
82
  meetings: TextFields<"loading" | "loadFailed" | "cancelConfirm" | "newStartPrompt" | "parseFailed" | "agenda" | "empty" | "unknown" | "drift" | "meet" | "reschedule" | "cancel">;
75
83
  admission: TextFields<"title" | "description" | "email" | "decision" | "expires" | "note" | "waive" | "require" | "add" | "ledger" | "loading" | "consumed" | "revoked" | "expired" | "active" | "local" | "parent" | "revoke">;
76
84
  network: AdminNetworkCopy;
77
- records: TextFields<"workflowMissing" | "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">;
85
+ records: AdminRecordsCopy;
78
86
  };
79
87
  }
80
88
  type DeepPartial<T> = T extends readonly (infer Item)[] ? readonly Item[] : T extends object ? {
@@ -885,6 +893,20 @@ interface IssuedMembershipOffer {
885
893
  digest: string;
886
894
  contract: MembershipCommercialOffer;
887
895
  }
896
+ /** What a join page may show before anyone applies: the current promise, without coupon ids or cohort counts. */
897
+ interface MembershipOfferPreview {
898
+ skuId: string;
899
+ offeringVersionId: string;
900
+ basePriceCents: number;
901
+ currency: string;
902
+ interval: "month" | "year";
903
+ founding: boolean;
904
+ cohortLabel?: string;
905
+ dueTodayCents: number;
906
+ renewalCents: number;
907
+ discountDuration?: "first_term" | "while_active";
908
+ initialTermEndsAt?: number;
909
+ }
888
910
 
889
911
  /** Server-owned source identity; the browser never supplies an offer or its price. */
890
912
  interface MembershipQuoteTarget {
@@ -1025,9 +1047,11 @@ interface MembershipChapterEffect extends MembershipQuoteTarget {
1025
1047
  seatId: string;
1026
1048
  kind: "invite_named_recipient" | "grant_named_recipient_access" | "revoke_named_recipient_access";
1027
1049
  }
1028
- /** Recover provider effects and expired invitations from durable state, independently of browser/webhook retries.
1050
+ /** Recover provider effects from durable state, independently of browser/webhook retries.
1029
1051
  * The optional chapter adapter must return a durable, idempotent receipt. An absent adapter leaves work visibly pending.
1030
1052
  * Provider HTTP timeouts, ambiguous receipts and scope conflicts never become success or an unbounded automatic retry loop.
1053
+ * An unaccepted seat is never refunded here: refunds are an operator decision (`refundNamedSeatByOperator`),
1054
+ * a recipient decline, a closed primary, or a provider-initiated refund.
1031
1055
  */
1032
1056
  declare function drainMembershipEffects(db: ChapterDb, options: {
1033
1057
  scope: MembershipEffectScope;
@@ -1040,7 +1064,6 @@ declare function drainMembershipEffects(db: ChapterDb, options: {
1040
1064
  }, now: number): Promise<{
1041
1065
  complete: number;
1042
1066
  pending: number;
1043
- expired: number;
1044
1067
  more: boolean;
1045
1068
  }>;
1046
1069
 
@@ -1055,6 +1078,22 @@ interface MembershipChapterEffectData extends MembershipChapterEffect {
1055
1078
  applicable: boolean;
1056
1079
  }
1057
1080
 
1081
+ /** Inputs supplied by an authenticated chapter backend; no browser credentials cross this edge. */
1082
+ interface RequestMembershipOfferOptions {
1083
+ secret: string;
1084
+ targetUrl: string;
1085
+ appId: string;
1086
+ chapterId: string;
1087
+ environment: string;
1088
+ runtime: string;
1089
+ applicationId: string;
1090
+ skuId: string;
1091
+ requestId: string;
1092
+ /** A configured service binding may replace public fetch, but must not fall back when absent. */
1093
+ fetch?: typeof globalThis.fetch;
1094
+ }
1095
+ /** Scope of a join-page preview; the browser never supplies it. */
1096
+ type MembershipOfferPreviewScope = Pick<RequestMembershipOfferOptions, "appId" | "chapterId" | "environment" | "runtime" | "skuId">;
1058
1097
  /** Only the named buyer's prepared payment details; no network credentials or canonical PII. */
1059
1098
  interface NamedSeatCheckoutReceipt {
1060
1099
  seatId: string;
@@ -1142,6 +1181,8 @@ interface ChapterWorkerOptions {
1142
1181
  * scope. Never implement these by promoting chapter-local projections to authority. */
1143
1182
  membershipAuthority?: {
1144
1183
  issueOffer: (input: Parameters<MembershipOfferIssuer>[0], env: ChapterEnv) => ReturnType<MembershipOfferIssuer>;
1184
+ /** Read-only founding preview for a join page; absent on older adapters, in which case tiers carry no preview. */
1185
+ previewOffer?: (input: MembershipOfferPreviewScope, env: ChapterEnv) => Promise<MembershipOfferPreview>;
1145
1186
  bindCheckout: (input: MembershipCheckoutBindingInput, env: ChapterEnv) => Promise<MembershipCheckoutBinding>;
1146
1187
  confirmPayment: (input: ConfirmMembershipPaymentInput, env: ChapterEnv) => Promise<MembershipPaymentReceipt>;
1147
1188
  approveMembership: (input: MembershipQuoteTarget, env: ChapterEnv) => Promise<MembershipPaymentReceipt>;
@@ -1173,8 +1214,18 @@ interface ChapterWorkerOptions {
1173
1214
  accept: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRecipientReceipt>;
1174
1215
  approve: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRecipientReceipt>;
1175
1216
  decline: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
1217
+ /** A verified super admin refunds one purchased seat; never automatic. */
1218
+ operatorRefund: (input: MembershipQuoteTarget & {
1219
+ seatId: string;
1220
+ }, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
1176
1221
  };
1177
1222
  };
1223
+ /** Network owner only: operate the membership authority this Worker hosts (seat refunds by a super admin).
1224
+ * `makeDb` must return the authority storage mapping, never a chapter projection. */
1225
+ membershipAuthorityOperator?: {
1226
+ makeDb: (env: ChapterEnv) => ChapterDb;
1227
+ stripeSecretName?: string;
1228
+ };
1178
1229
  /** CRM mount point. Default "/api/crm". */
1179
1230
  crmBasePath?: string;
1180
1231
  /** Host routes, tried BEFORE the built-ins — so a wrapping site can add its own
@@ -1210,6 +1261,8 @@ declare function createWorkerContext(options: ChapterWorkerOptions): {
1210
1261
  requirePaymentQuote: boolean;
1211
1262
  membershipAuthority: {
1212
1263
  issueOffer: (input: Parameters<MembershipOfferIssuer>[0], env: ChapterEnv) => ReturnType<MembershipOfferIssuer>;
1264
+ /** Read-only founding preview for a join page; absent on older adapters, in which case tiers carry no preview. */
1265
+ previewOffer?: (input: MembershipOfferPreviewScope, env: ChapterEnv) => Promise<MembershipOfferPreview>;
1213
1266
  bindCheckout: (input: MembershipCheckoutBindingInput, env: ChapterEnv) => Promise<MembershipCheckoutBinding>;
1214
1267
  confirmPayment: (input: ConfirmMembershipPaymentInput, env: ChapterEnv) => Promise<MembershipPaymentReceipt>;
1215
1268
  approveMembership: (input: MembershipQuoteTarget, env: ChapterEnv) => Promise<MembershipPaymentReceipt>;
@@ -1241,8 +1294,16 @@ declare function createWorkerContext(options: ChapterWorkerOptions): {
1241
1294
  accept: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRecipientReceipt>;
1242
1295
  approve: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRecipientReceipt>;
1243
1296
  decline: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
1297
+ /** A verified super admin refunds one purchased seat; never automatic. */
1298
+ operatorRefund: (input: MembershipQuoteTarget & {
1299
+ seatId: string;
1300
+ }, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
1244
1301
  };
1245
1302
  } | undefined;
1303
+ membershipAuthorityOperator: {
1304
+ makeDb: (env: ChapterEnv) => ChapterDb;
1305
+ stripeSecretName?: string;
1306
+ } | undefined;
1246
1307
  getPublicConfig: (env: ChapterEnv) => Promise<PublicConfig>;
1247
1308
  verifyUser: (req: Request, env: ChapterEnv) => Promise<Verified | null>;
1248
1309
  makeDb: (env: ChapterEnv) => Db;
@@ -1302,6 +1363,21 @@ declare function createMembershipAuthorityHandler(options: MembershipAuthorityHa
1302
1363
  */
1303
1364
  declare function createMembershipAuthorityStorage(db: ChapterDb, secretNames: readonly string[]): ChapterDb;
1304
1365
 
1366
+ /** Identity of one purchased seat inside its exact network scope. */
1367
+ type NamedSeatOperatorRefundInput = MembershipQuoteTarget & {
1368
+ seatId: string;
1369
+ };
1370
+ /** Refund one purchased named seat because a verified super admin decided to.
1371
+ * Nothing here is automatic or time-driven: the caller has already authenticated
1372
+ * the operator on the chapter or on the network owner. The primary subscription
1373
+ * is never canceled; an accepted recipient loses access through the durable
1374
+ * revoke effect, and a replay after the refund is idempotent.
1375
+ */
1376
+ declare function refundNamedSeatByOperator(db: ChapterDb, input: NamedSeatOperatorRefundInput, stripeSecretKey: string, now: number): Promise<NamedSeatRefundReceipt>;
1377
+
1378
+ /** Reasons a purchased seat may be refunded. No reason is time-driven: an unaccepted seat waits for a person. */
1379
+ type NamedSeatRefundReason = "declined" | "operator" | "primary_closed" | "provider_refund";
1380
+
1305
1381
  type Row = Record<string, unknown>;
1306
1382
  /** Host routes may reuse this gate after resolving a verified chapter/runtime account. */
1307
1383
  declare function chapterMembershipAccess(db: ChapterDb, env: ChapterEnv, ctx: WorkerContext, app: Row): Promise<boolean>;
@@ -1920,4 +1996,4 @@ declare function chapterWorker(options: ChapterWorkerOptions): {
1920
1996
  fetch(req: Request, env: ChapterEnv): Promise<Response>;
1921
1997
  };
1922
1998
 
1923
- export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, AdmissionGrantDeliveryError, type AdmissionGrantDeliveryOptions, type BuilderLibraryDeliveryOptions, type ChapterEnv, type ChapterWorkerOptions, type LeaderAdmissionAssignment, type LeaderAdmissionDelivery, type LeaderAdmissionDeliveryStatus, MEMBERSHIP_AUTHORITY_PATH, type MemberContentDeliveryOptions, type MembershipAuthorityHandlerOptions, type MembershipAuthorityPeer, type MembershipChapterEffect, type MembershipEffectScope, type MembershipWorkerAdapter, type MembershipWorkerAdapterOptions, type NetworkTargetTransport, NetworkTargetTransportError, type Route, type SignupControlDeliveryOptions, type WorkerContext, chapterMembershipAccess, chapterWorker, createMembershipAuthorityHandler, createMembershipAuthorityStorage, createMembershipChapterEffectRoute, createMembershipWorkerAdapter, createWorkerContext, deliverAdmissionGrants, deliverBuilderLibrary, deliverMemberContent, deliverMembershipChapterEffect, deliverSignupControl, drainMembershipEffects, renderActiveSignupControlHtml, resolveNetworkTargetTransport, retryChapterApprovalEffects, retryLeaderAdmissionDeliveries, withActiveSignupControlTheme };
1999
+ export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, AdmissionGrantDeliveryError, type AdmissionGrantDeliveryOptions, type BuilderLibraryDeliveryOptions, type ChapterEnv, type ChapterWorkerOptions, type LeaderAdmissionAssignment, type LeaderAdmissionDelivery, type LeaderAdmissionDeliveryStatus, MEMBERSHIP_AUTHORITY_PATH, type MemberContentDeliveryOptions, type MembershipAuthorityHandlerOptions, type MembershipAuthorityPeer, type MembershipChapterEffect, type MembershipEffectScope, type MembershipWorkerAdapter, type MembershipWorkerAdapterOptions, type NamedSeatOperatorRefundInput, type NamedSeatRefundReason, type NetworkTargetTransport, NetworkTargetTransportError, type Route, type SignupControlDeliveryOptions, type WorkerContext, chapterMembershipAccess, chapterWorker, createMembershipAuthorityHandler, createMembershipAuthorityStorage, createMembershipChapterEffectRoute, createMembershipWorkerAdapter, createWorkerContext, deliverAdmissionGrants, deliverBuilderLibrary, deliverMemberContent, deliverMembershipChapterEffect, deliverSignupControl, drainMembershipEffects, refundNamedSeatByOperator, renderActiveSignupControlHtml, resolveNetworkTargetTransport, retryChapterApprovalEffects, retryLeaderAdmissionDeliveries, withActiveSignupControlTheme };
@@ -27,9 +27,17 @@ type TextFields$1<Key extends string> = {
27
27
  /** User-visible language for sharing, delivery state, and leader rollups. */
28
28
  type AdminNetworkCopy = TextFields$1<"title" | "allowlistDescription" | "sharing" | "shareWith" | "shared" | "shareFailed" | "deliveryFailed" | "loadingRollup" | "loadRollupFailed" | "overview" | "configuredFollowers" | "reachableFollowers" | "recordsAcrossFollowers" | "noFollowers" | "followers" | "available" | "unavailable" | "transportReachable" | "transportUnavailable" | "transportNotChecked" | "bindingTransport" | "urlTransport" | "activeConfiguration" | "noActiveConfiguration" | "publicSiteAvailable" | "publicSiteUnavailable" | "publicSiteNotChecked" | "recordTotals" | "noRecordTotals">;
29
29
 
30
+ /** Copy for the person record panels: lifecycle actions, comms, scheduling, billing and meetings. */
31
+ type AdminRecordsCopy = {
32
+ [Field in AdminRecordsCopyKey]: string;
33
+ };
34
+ /** Every key a host may override under `admin.records`. */
35
+ 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";
36
+
30
37
  type TextFields<Key extends string> = {
31
38
  [Field in Key]: string;
32
39
  };
40
+
33
41
  /** Complete serializable language for Chapter surfaces; use render slots for markup and `formatChapterCopy()` for placeholders. */
34
42
  interface ChapterCopy {
35
43
  common: TextFields<"loading" | "saved" | "unknown">;
@@ -48,7 +56,7 @@ interface ChapterCopy {
48
56
  * agree rather than merely restating the policy. Set it to an empty string
49
57
  * to render the checkbox with the policy as its only label.
50
58
  */
51
- payment: TextFields<"setupFailed" | "preparing" | "pending" | "processing" | "payAndContinue" | "incomplete" | "consent">;
59
+ payment: TextFields<"setupFailed" | "preparing" | "pending" | "processing" | "payAndContinue" | "incomplete" | "consent" | "foundingMember" | "foundingDiscount">;
52
60
  done: TextFields<"label" | "calendarInvite" | "memberArea">;
53
61
  accepted: TextFields<"label" | "body">;
54
62
  gift: TextFields<"chooseSelf" | "optionsLabel" | "label" | "body" | "save" | "rotate" | "rotateFailed" | "claimTitle" | "claimBody" | "code" | "redeem" | "redeemed" | "redeemFailed">;
@@ -74,7 +82,7 @@ interface ChapterCopy {
74
82
  meetings: TextFields<"loading" | "loadFailed" | "cancelConfirm" | "newStartPrompt" | "parseFailed" | "agenda" | "empty" | "unknown" | "drift" | "meet" | "reschedule" | "cancel">;
75
83
  admission: TextFields<"title" | "description" | "email" | "decision" | "expires" | "note" | "waive" | "require" | "add" | "ledger" | "loading" | "consumed" | "revoked" | "expired" | "active" | "local" | "parent" | "revoke">;
76
84
  network: AdminNetworkCopy;
77
- records: TextFields<"workflowMissing" | "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">;
85
+ records: AdminRecordsCopy;
78
86
  };
79
87
  }
80
88
  type DeepPartial<T> = T extends readonly (infer Item)[] ? readonly Item[] : T extends object ? {
@@ -885,6 +893,20 @@ interface IssuedMembershipOffer {
885
893
  digest: string;
886
894
  contract: MembershipCommercialOffer;
887
895
  }
896
+ /** What a join page may show before anyone applies: the current promise, without coupon ids or cohort counts. */
897
+ interface MembershipOfferPreview {
898
+ skuId: string;
899
+ offeringVersionId: string;
900
+ basePriceCents: number;
901
+ currency: string;
902
+ interval: "month" | "year";
903
+ founding: boolean;
904
+ cohortLabel?: string;
905
+ dueTodayCents: number;
906
+ renewalCents: number;
907
+ discountDuration?: "first_term" | "while_active";
908
+ initialTermEndsAt?: number;
909
+ }
888
910
 
889
911
  /** Server-owned source identity; the browser never supplies an offer or its price. */
890
912
  interface MembershipQuoteTarget {
@@ -1025,9 +1047,11 @@ interface MembershipChapterEffect extends MembershipQuoteTarget {
1025
1047
  seatId: string;
1026
1048
  kind: "invite_named_recipient" | "grant_named_recipient_access" | "revoke_named_recipient_access";
1027
1049
  }
1028
- /** Recover provider effects and expired invitations from durable state, independently of browser/webhook retries.
1050
+ /** Recover provider effects from durable state, independently of browser/webhook retries.
1029
1051
  * The optional chapter adapter must return a durable, idempotent receipt. An absent adapter leaves work visibly pending.
1030
1052
  * Provider HTTP timeouts, ambiguous receipts and scope conflicts never become success or an unbounded automatic retry loop.
1053
+ * An unaccepted seat is never refunded here: refunds are an operator decision (`refundNamedSeatByOperator`),
1054
+ * a recipient decline, a closed primary, or a provider-initiated refund.
1031
1055
  */
1032
1056
  declare function drainMembershipEffects(db: ChapterDb, options: {
1033
1057
  scope: MembershipEffectScope;
@@ -1040,7 +1064,6 @@ declare function drainMembershipEffects(db: ChapterDb, options: {
1040
1064
  }, now: number): Promise<{
1041
1065
  complete: number;
1042
1066
  pending: number;
1043
- expired: number;
1044
1067
  more: boolean;
1045
1068
  }>;
1046
1069
 
@@ -1055,6 +1078,22 @@ interface MembershipChapterEffectData extends MembershipChapterEffect {
1055
1078
  applicable: boolean;
1056
1079
  }
1057
1080
 
1081
+ /** Inputs supplied by an authenticated chapter backend; no browser credentials cross this edge. */
1082
+ interface RequestMembershipOfferOptions {
1083
+ secret: string;
1084
+ targetUrl: string;
1085
+ appId: string;
1086
+ chapterId: string;
1087
+ environment: string;
1088
+ runtime: string;
1089
+ applicationId: string;
1090
+ skuId: string;
1091
+ requestId: string;
1092
+ /** A configured service binding may replace public fetch, but must not fall back when absent. */
1093
+ fetch?: typeof globalThis.fetch;
1094
+ }
1095
+ /** Scope of a join-page preview; the browser never supplies it. */
1096
+ type MembershipOfferPreviewScope = Pick<RequestMembershipOfferOptions, "appId" | "chapterId" | "environment" | "runtime" | "skuId">;
1058
1097
  /** Only the named buyer's prepared payment details; no network credentials or canonical PII. */
1059
1098
  interface NamedSeatCheckoutReceipt {
1060
1099
  seatId: string;
@@ -1142,6 +1181,8 @@ interface ChapterWorkerOptions {
1142
1181
  * scope. Never implement these by promoting chapter-local projections to authority. */
1143
1182
  membershipAuthority?: {
1144
1183
  issueOffer: (input: Parameters<MembershipOfferIssuer>[0], env: ChapterEnv) => ReturnType<MembershipOfferIssuer>;
1184
+ /** Read-only founding preview for a join page; absent on older adapters, in which case tiers carry no preview. */
1185
+ previewOffer?: (input: MembershipOfferPreviewScope, env: ChapterEnv) => Promise<MembershipOfferPreview>;
1145
1186
  bindCheckout: (input: MembershipCheckoutBindingInput, env: ChapterEnv) => Promise<MembershipCheckoutBinding>;
1146
1187
  confirmPayment: (input: ConfirmMembershipPaymentInput, env: ChapterEnv) => Promise<MembershipPaymentReceipt>;
1147
1188
  approveMembership: (input: MembershipQuoteTarget, env: ChapterEnv) => Promise<MembershipPaymentReceipt>;
@@ -1173,8 +1214,18 @@ interface ChapterWorkerOptions {
1173
1214
  accept: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRecipientReceipt>;
1174
1215
  approve: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRecipientReceipt>;
1175
1216
  decline: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
1217
+ /** A verified super admin refunds one purchased seat; never automatic. */
1218
+ operatorRefund: (input: MembershipQuoteTarget & {
1219
+ seatId: string;
1220
+ }, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
1176
1221
  };
1177
1222
  };
1223
+ /** Network owner only: operate the membership authority this Worker hosts (seat refunds by a super admin).
1224
+ * `makeDb` must return the authority storage mapping, never a chapter projection. */
1225
+ membershipAuthorityOperator?: {
1226
+ makeDb: (env: ChapterEnv) => ChapterDb;
1227
+ stripeSecretName?: string;
1228
+ };
1178
1229
  /** CRM mount point. Default "/api/crm". */
1179
1230
  crmBasePath?: string;
1180
1231
  /** Host routes, tried BEFORE the built-ins — so a wrapping site can add its own
@@ -1210,6 +1261,8 @@ declare function createWorkerContext(options: ChapterWorkerOptions): {
1210
1261
  requirePaymentQuote: boolean;
1211
1262
  membershipAuthority: {
1212
1263
  issueOffer: (input: Parameters<MembershipOfferIssuer>[0], env: ChapterEnv) => ReturnType<MembershipOfferIssuer>;
1264
+ /** Read-only founding preview for a join page; absent on older adapters, in which case tiers carry no preview. */
1265
+ previewOffer?: (input: MembershipOfferPreviewScope, env: ChapterEnv) => Promise<MembershipOfferPreview>;
1213
1266
  bindCheckout: (input: MembershipCheckoutBindingInput, env: ChapterEnv) => Promise<MembershipCheckoutBinding>;
1214
1267
  confirmPayment: (input: ConfirmMembershipPaymentInput, env: ChapterEnv) => Promise<MembershipPaymentReceipt>;
1215
1268
  approveMembership: (input: MembershipQuoteTarget, env: ChapterEnv) => Promise<MembershipPaymentReceipt>;
@@ -1241,8 +1294,16 @@ declare function createWorkerContext(options: ChapterWorkerOptions): {
1241
1294
  accept: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRecipientReceipt>;
1242
1295
  approve: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRecipientReceipt>;
1243
1296
  decline: (input: NamedSeatRecipientInput, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
1297
+ /** A verified super admin refunds one purchased seat; never automatic. */
1298
+ operatorRefund: (input: MembershipQuoteTarget & {
1299
+ seatId: string;
1300
+ }, env: ChapterEnv) => Promise<NamedSeatRefundReceipt>;
1244
1301
  };
1245
1302
  } | undefined;
1303
+ membershipAuthorityOperator: {
1304
+ makeDb: (env: ChapterEnv) => ChapterDb;
1305
+ stripeSecretName?: string;
1306
+ } | undefined;
1246
1307
  getPublicConfig: (env: ChapterEnv) => Promise<PublicConfig>;
1247
1308
  verifyUser: (req: Request, env: ChapterEnv) => Promise<Verified | null>;
1248
1309
  makeDb: (env: ChapterEnv) => Db;
@@ -1302,6 +1363,21 @@ declare function createMembershipAuthorityHandler(options: MembershipAuthorityHa
1302
1363
  */
1303
1364
  declare function createMembershipAuthorityStorage(db: ChapterDb, secretNames: readonly string[]): ChapterDb;
1304
1365
 
1366
+ /** Identity of one purchased seat inside its exact network scope. */
1367
+ type NamedSeatOperatorRefundInput = MembershipQuoteTarget & {
1368
+ seatId: string;
1369
+ };
1370
+ /** Refund one purchased named seat because a verified super admin decided to.
1371
+ * Nothing here is automatic or time-driven: the caller has already authenticated
1372
+ * the operator on the chapter or on the network owner. The primary subscription
1373
+ * is never canceled; an accepted recipient loses access through the durable
1374
+ * revoke effect, and a replay after the refund is idempotent.
1375
+ */
1376
+ declare function refundNamedSeatByOperator(db: ChapterDb, input: NamedSeatOperatorRefundInput, stripeSecretKey: string, now: number): Promise<NamedSeatRefundReceipt>;
1377
+
1378
+ /** Reasons a purchased seat may be refunded. No reason is time-driven: an unaccepted seat waits for a person. */
1379
+ type NamedSeatRefundReason = "declined" | "operator" | "primary_closed" | "provider_refund";
1380
+
1305
1381
  type Row = Record<string, unknown>;
1306
1382
  /** Host routes may reuse this gate after resolving a verified chapter/runtime account. */
1307
1383
  declare function chapterMembershipAccess(db: ChapterDb, env: ChapterEnv, ctx: WorkerContext, app: Row): Promise<boolean>;
@@ -1920,4 +1996,4 @@ declare function chapterWorker(options: ChapterWorkerOptions): {
1920
1996
  fetch(req: Request, env: ChapterEnv): Promise<Response>;
1921
1997
  };
1922
1998
 
1923
- export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, AdmissionGrantDeliveryError, type AdmissionGrantDeliveryOptions, type BuilderLibraryDeliveryOptions, type ChapterEnv, type ChapterWorkerOptions, type LeaderAdmissionAssignment, type LeaderAdmissionDelivery, type LeaderAdmissionDeliveryStatus, MEMBERSHIP_AUTHORITY_PATH, type MemberContentDeliveryOptions, type MembershipAuthorityHandlerOptions, type MembershipAuthorityPeer, type MembershipChapterEffect, type MembershipEffectScope, type MembershipWorkerAdapter, type MembershipWorkerAdapterOptions, type NetworkTargetTransport, NetworkTargetTransportError, type Route, type SignupControlDeliveryOptions, type WorkerContext, chapterMembershipAccess, chapterWorker, createMembershipAuthorityHandler, createMembershipAuthorityStorage, createMembershipChapterEffectRoute, createMembershipWorkerAdapter, createWorkerContext, deliverAdmissionGrants, deliverBuilderLibrary, deliverMemberContent, deliverMembershipChapterEffect, deliverSignupControl, drainMembershipEffects, renderActiveSignupControlHtml, resolveNetworkTargetTransport, retryChapterApprovalEffects, retryLeaderAdmissionDeliveries, withActiveSignupControlTheme };
1999
+ export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, AdmissionGrantDeliveryError, type AdmissionGrantDeliveryOptions, type BuilderLibraryDeliveryOptions, type ChapterEnv, type ChapterWorkerOptions, type LeaderAdmissionAssignment, type LeaderAdmissionDelivery, type LeaderAdmissionDeliveryStatus, MEMBERSHIP_AUTHORITY_PATH, type MemberContentDeliveryOptions, type MembershipAuthorityHandlerOptions, type MembershipAuthorityPeer, type MembershipChapterEffect, type MembershipEffectScope, type MembershipWorkerAdapter, type MembershipWorkerAdapterOptions, type NamedSeatOperatorRefundInput, type NamedSeatRefundReason, type NetworkTargetTransport, NetworkTargetTransportError, type Route, type SignupControlDeliveryOptions, type WorkerContext, chapterMembershipAccess, chapterWorker, createMembershipAuthorityHandler, createMembershipAuthorityStorage, createMembershipChapterEffectRoute, createMembershipWorkerAdapter, createWorkerContext, deliverAdmissionGrants, deliverBuilderLibrary, deliverMemberContent, deliverMembershipChapterEffect, deliverSignupControl, drainMembershipEffects, refundNamedSeatByOperator, renderActiveSignupControlHtml, resolveNetworkTargetTransport, retryChapterApprovalEffects, retryLeaderAdmissionDeliveries, withActiveSignupControlTheme };