@odla-ai/chapter 0.50.0 → 0.52.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 +109 -8
- package/dist/{chunk-4EA5V4JE.js → chunk-7N4VDWM5.js} +239 -136
- package/dist/chunk-7N4VDWM5.js.map +1 -0
- package/dist/{chunk-OS46ZE46.js → chunk-7RIT2UN5.js} +3 -7
- package/dist/chunk-7RIT2UN5.js.map +1 -0
- package/dist/{chunk-JXX4BFDP.js → chunk-A6W53GVM.js} +5 -1
- package/dist/chunk-A6W53GVM.js.map +1 -0
- package/dist/{copy-context-Ddat__H5.d.ts → copy-context-CYLlPzAc.d.ts} +11 -5
- package/dist/index.cjs +111 -18
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +77 -13
- package/dist/index.d.ts +77 -13
- package/dist/index.js +111 -18
- package/dist/index.js.map +1 -1
- package/dist/ui/admin/index.d.ts +14 -3
- package/dist/ui/admin/index.js +4 -2
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.js +5 -3
- package/dist/ui/member/index.d.ts +2 -2
- package/dist/ui/member/index.js +2 -2
- package/dist/worker/index.cjs +983 -368
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +52 -10
- package/dist/worker/index.d.ts +52 -10
- package/dist/worker/index.js +983 -368
- package/dist/worker/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/chunk-4EA5V4JE.js.map +0 -1
- package/dist/chunk-JXX4BFDP.js.map +0 -1
- package/dist/chunk-OS46ZE46.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -502,7 +502,7 @@ var giftRedemptionAttemptsEntity = { attrs: {
|
|
|
502
502
|
} };
|
|
503
503
|
|
|
504
504
|
// src/payment-recovery-schema.ts
|
|
505
|
-
var field = (type, unique = false) => ({ type, unique, indexed: type !== "json", optional
|
|
505
|
+
var field = (type, unique = false, optional = false) => ({ type, unique, indexed: type !== "json", optional });
|
|
506
506
|
var paymentRecoveryReviewsEntity = { attrs: {
|
|
507
507
|
id: field("string", true),
|
|
508
508
|
eventId: field("string"),
|
|
@@ -511,7 +511,9 @@ var paymentRecoveryReviewsEntity = { attrs: {
|
|
|
511
511
|
previousDigest: field("string"),
|
|
512
512
|
providerDigest: field("string"),
|
|
513
513
|
scope: field("string"),
|
|
514
|
-
previousState: field("json")
|
|
514
|
+
previousState: field("json"),
|
|
515
|
+
action: field("string", false, true),
|
|
516
|
+
reason: field("string", false, true)
|
|
515
517
|
} };
|
|
516
518
|
|
|
517
519
|
// src/schema-stripe.ts
|
|
@@ -707,7 +709,7 @@ var boolean = (flags = {}) => ({
|
|
|
707
709
|
indexed: flags.indexed ?? false,
|
|
708
710
|
optional: false
|
|
709
711
|
});
|
|
710
|
-
var json2 = () => ({ type: "json", unique: false, indexed: false, optional: false });
|
|
712
|
+
var json2 = (flags = {}) => ({ type: "json", unique: false, indexed: false, optional: flags.optional ?? false });
|
|
711
713
|
var id4 = () => string2({ unique: true, indexed: true });
|
|
712
714
|
var events = { attrs: {
|
|
713
715
|
id: id4(),
|
|
@@ -736,6 +738,10 @@ var exceptions = { attrs: {
|
|
|
736
738
|
status: string2({ indexed: true }),
|
|
737
739
|
resolvedDigest: string2({ optional: true }),
|
|
738
740
|
incomingDigest: string2({ optional: true }),
|
|
741
|
+
incomingFact: json2({ optional: true }),
|
|
742
|
+
reviewedDigest: string2({ optional: true }),
|
|
743
|
+
resolvedBy: string2({ optional: true }),
|
|
744
|
+
reviewId: string2({ optional: true }),
|
|
739
745
|
detail: json2(),
|
|
740
746
|
updatedAt: number2({ indexed: true })
|
|
741
747
|
} };
|
|
@@ -874,6 +880,7 @@ var groups = {
|
|
|
874
880
|
stripePublishableKey: attr7("string", { optional: true }),
|
|
875
881
|
notificationEmail: attr7("string"),
|
|
876
882
|
replyTo: attr7("string"),
|
|
883
|
+
fromName: attr7("string", { optional: true }),
|
|
877
884
|
debugEmail: attr7("string", { optional: true }),
|
|
878
885
|
calendarLink: attr7("string", { optional: true }),
|
|
879
886
|
disclaimerText: attr7("string"),
|
|
@@ -1070,6 +1077,13 @@ function defaultCrm(mode) {
|
|
|
1070
1077
|
};
|
|
1071
1078
|
}
|
|
1072
1079
|
|
|
1080
|
+
// src/named-seat-accepted-template.ts
|
|
1081
|
+
var SEAT_ACCEPTED_TEMPLATE = {
|
|
1082
|
+
enabled: true,
|
|
1083
|
+
subject: "{{recipientName}} accepted your {{chapterName}} seat",
|
|
1084
|
+
text: "Hi {{firstName}},\n\n{{recipientName}} has accepted the {{tierName}} seat you purchased at {{chapterName}}. They will complete their own application and any membership requirements from here; nothing more is needed from you.\n\nWarmly,\n{{chapterName}}"
|
|
1085
|
+
};
|
|
1086
|
+
|
|
1073
1087
|
// src/group.ts
|
|
1074
1088
|
var DEFAULT_SCHEDULING = {
|
|
1075
1089
|
slotMinutes: 45,
|
|
@@ -1091,7 +1105,16 @@ ${name}`;
|
|
|
1091
1105
|
text: `A new application came in for ${name}.
|
|
1092
1106
|
|
|
1093
1107
|
Name: {{firstName}} {{lastName}}
|
|
1094
|
-
Email: {{email}}
|
|
1108
|
+
Email: {{email}}
|
|
1109
|
+
Tier: {{tier}}
|
|
1110
|
+
|
|
1111
|
+
Review it: {{adminUrl}}`
|
|
1112
|
+
},
|
|
1113
|
+
submitConfirmation: {
|
|
1114
|
+
subject: `We received your application to ${name}`,
|
|
1115
|
+
text: `Hi {{firstName}},
|
|
1116
|
+
|
|
1117
|
+
Thanks for applying to ${name}. {{submitNextStep}}${sign}`
|
|
1095
1118
|
},
|
|
1096
1119
|
paymentConfirmation: {
|
|
1097
1120
|
subject: `Welcome to ${name}`,
|
|
@@ -1103,14 +1126,17 @@ Your membership payment{{paymentAmountSummary}} is confirmed. {{paymentNextStep}
|
|
|
1103
1126
|
subject: `Your ${name} intro call`,
|
|
1104
1127
|
text: `Hi {{firstName}},
|
|
1105
1128
|
|
|
1106
|
-
Looking forward to our call
|
|
1129
|
+
You are all set{{paymentAmountSummary}}. Looking forward to our call on {{startAt}}.
|
|
1130
|
+
|
|
1131
|
+
Join here: {{meetingLink}}${sign}`
|
|
1107
1132
|
},
|
|
1108
1133
|
onboardingInvite: {
|
|
1109
1134
|
subject: `You're in, ${name}`,
|
|
1110
1135
|
text: `Hi {{firstName}},
|
|
1111
1136
|
|
|
1112
1137
|
Welcome to ${name}. Your member area is here: {{membersUrl}}${sign}`
|
|
1113
|
-
}
|
|
1138
|
+
},
|
|
1139
|
+
seatAccepted: SEAT_ACCEPTED_TEMPLATE
|
|
1114
1140
|
};
|
|
1115
1141
|
}
|
|
1116
1142
|
function buildGroupSeed(config) {
|
|
@@ -1139,6 +1165,7 @@ function buildGroupSeed(config) {
|
|
|
1139
1165
|
schedulingJson: scheduling
|
|
1140
1166
|
};
|
|
1141
1167
|
if (emails?.debugEmail) row2.debugEmail = emails.debugEmail;
|
|
1168
|
+
if (emails?.fromName?.trim()) row2.fromName = emails.fromName.trim();
|
|
1142
1169
|
if (policy.commitmentText) row2.commitmentText = policy.commitmentText;
|
|
1143
1170
|
if (policy.normsText) row2.normsText = policy.normsText;
|
|
1144
1171
|
return row2;
|
|
@@ -1359,6 +1386,8 @@ var DEFAULT_ADMIN_COPY = {
|
|
|
1359
1386
|
delivery: "Delivery",
|
|
1360
1387
|
notificationAddress: "Notification address",
|
|
1361
1388
|
replyTo: "Reply-to",
|
|
1389
|
+
fromName: "From name",
|
|
1390
|
+
fromNameHint: "Shown as the sender; the address stays the Worker's configured one.",
|
|
1362
1391
|
debugInbox: "Debug inbox",
|
|
1363
1392
|
debugInboxHint: "Non-production sends redirect here.",
|
|
1364
1393
|
sendTest: "Send test",
|
|
@@ -1430,6 +1459,8 @@ var DEFAULT_ADMIN_COPY = {
|
|
|
1430
1459
|
transportReachable: "transport reachable",
|
|
1431
1460
|
transportUnavailable: "transport unavailable",
|
|
1432
1461
|
transportNotChecked: "transport not checked",
|
|
1462
|
+
edgeUnpaired: "edge unpaired",
|
|
1463
|
+
edgeUnpairedHint: "This follower's shared secret is not in the leader vault, so nothing can be signed. Pair both vaults from an enrolled machine:",
|
|
1433
1464
|
bindingTransport: "service binding {binding}",
|
|
1434
1465
|
urlTransport: "public URL transport",
|
|
1435
1466
|
activeConfiguration: "active configuration r{revision}",
|
|
@@ -2158,6 +2189,10 @@ function defineChapter(config) {
|
|
|
2158
2189
|
if (!config.emails || typeof config.emails.notificationEmail !== "string" || config.emails.notificationEmail === "") {
|
|
2159
2190
|
throw new Error("defineChapter.emails.notificationEmail: required in chapter mode");
|
|
2160
2191
|
}
|
|
2192
|
+
const fromName = config.emails.fromName;
|
|
2193
|
+
if (fromName !== void 0 && (typeof fromName !== "string" || /[\r\n<>]/.test(fromName) || fromName.trim().length > 100)) {
|
|
2194
|
+
throw new Error("defineChapter.emails.fromName: must be one line of at most 100 characters with no angle brackets");
|
|
2195
|
+
}
|
|
2161
2196
|
if (!config.prices || typeof config.prices.standardCents !== "number") {
|
|
2162
2197
|
throw new Error("defineChapter.prices.standardCents: required in chapter mode");
|
|
2163
2198
|
}
|
|
@@ -3153,6 +3188,7 @@ function createChapterIntegration(chapter, options = {}) {
|
|
|
3153
3188
|
description: "Signing secret for the read-only network commercial Stripe webhook endpoint.",
|
|
3154
3189
|
required: true
|
|
3155
3190
|
});
|
|
3191
|
+
secrets.push(...federationEdgeSecrets(chapter));
|
|
3156
3192
|
return {
|
|
3157
3193
|
id: "chapter",
|
|
3158
3194
|
title: `Chapter: ${chapter.name}`,
|
|
@@ -3196,8 +3232,48 @@ function createChapterIntegration(chapter, options = {}) {
|
|
|
3196
3232
|
runbooks
|
|
3197
3233
|
};
|
|
3198
3234
|
}
|
|
3235
|
+
function federationEdgeSecrets(chapter) {
|
|
3236
|
+
const secrets = chapter.network.targets.map((target) => ({
|
|
3237
|
+
name: target.secretName,
|
|
3238
|
+
description: `Shared secret for the signed federation edge to follower "${target.id}"; pair both vaults with "odla-ai chapter edge pair --leader ${chapter.id} --follower ${target.id}".`,
|
|
3239
|
+
required: true,
|
|
3240
|
+
edge: { role: "leader", peers: [target.id] }
|
|
3241
|
+
}));
|
|
3242
|
+
const peers = [.../* @__PURE__ */ new Set([
|
|
3243
|
+
...chapter.network.readers.map((reader) => reader.id),
|
|
3244
|
+
...(chapter.builderLibrary?.sources ?? []).map((source) => source.sourceId)
|
|
3245
|
+
])];
|
|
3246
|
+
if (peers.length > 0) secrets.push({
|
|
3247
|
+
name: "network_share_secret",
|
|
3248
|
+
description: `Shared secret every declared leader (${peers.join(", ")}) signs federation requests with; pair it with "odla-ai chapter edge pair --leader <leader> --follower ${chapter.id}".`,
|
|
3249
|
+
required: true,
|
|
3250
|
+
edge: { role: "follower", peers }
|
|
3251
|
+
});
|
|
3252
|
+
return secrets;
|
|
3253
|
+
}
|
|
3254
|
+
|
|
3255
|
+
// src/network-edge.ts
|
|
3256
|
+
var EDGE_UNPAIRED = "edge_unpaired";
|
|
3257
|
+
function pairingCommand(leaderId, targetId, env) {
|
|
3258
|
+
const scope2 = env ? ` --env ${env}` : "";
|
|
3259
|
+
return `odla-ai chapter edge pair --leader ${leaderId} --follower ${targetId}${scope2}`;
|
|
3260
|
+
}
|
|
3261
|
+
function edgeUnpaired(leaderId, target, env) {
|
|
3262
|
+
return {
|
|
3263
|
+
code: EDGE_UNPAIRED,
|
|
3264
|
+
target: target.id,
|
|
3265
|
+
secretName: target.secretName,
|
|
3266
|
+
message: `edge to "${target.id}" is unpaired: leader vault slot "${target.secretName}" is empty`,
|
|
3267
|
+
hint: pairingCommand(leaderId, target.id, env)
|
|
3268
|
+
};
|
|
3269
|
+
}
|
|
3199
3270
|
|
|
3200
3271
|
// src/membership-policy.ts
|
|
3272
|
+
function seatPurchaseDeadline(offering, member) {
|
|
3273
|
+
if (offering.seatPurchaseWindowCalendarMonths === void 0) return Number(member.termEndsAt);
|
|
3274
|
+
if (Number.isSafeInteger(member.seatPurchaseEndsAt)) return Number(member.seatPurchaseEndsAt);
|
|
3275
|
+
return addMembershipCalendarMonths(Number(member.initialTermStartedAt ?? member.termStartedAt), offering.seatPurchaseWindowCalendarMonths);
|
|
3276
|
+
}
|
|
3201
3277
|
var fail2 = (field2) => {
|
|
3202
3278
|
throw new TypeError(`invalid membership policy: ${field2}`);
|
|
3203
3279
|
};
|
|
@@ -3254,7 +3330,7 @@ function membershipOfferingVersion(value) {
|
|
|
3254
3330
|
autoRenew: true,
|
|
3255
3331
|
paymentGraceDays: integer2(input.paymentGraceDays, 0, 60),
|
|
3256
3332
|
seatPriceCents: integer2(input.seatPriceCents, 1, Number.MAX_SAFE_INTEGER),
|
|
3257
|
-
seatPurchaseWindowCalendarMonths: integer2(input.seatPurchaseWindowCalendarMonths, 1, 120),
|
|
3333
|
+
...input.seatPurchaseWindowCalendarMonths === void 0 || input.seatPurchaseWindowCalendarMonths === null ? {} : { seatPurchaseWindowCalendarMonths: integer2(input.seatPurchaseWindowCalendarMonths, 1, 120) },
|
|
3258
3334
|
requiredDisclosures: ids(input.requiredDisclosures)
|
|
3259
3335
|
};
|
|
3260
3336
|
}
|
|
@@ -3648,7 +3724,7 @@ async function confirmMembershipPayment(db, input, now) {
|
|
|
3648
3724
|
initialTermEndsAt: endsAt,
|
|
3649
3725
|
termStartedAt: paidAt,
|
|
3650
3726
|
termEndsAt: endsAt,
|
|
3651
|
-
seatPurchaseEndsAt:
|
|
3727
|
+
seatPurchaseEndsAt: seatPurchaseDeadline(offering, { initialTermStartedAt: paidAt, termEndsAt: endsAt }),
|
|
3652
3728
|
autoRenew: true,
|
|
3653
3729
|
refundedCents: 0,
|
|
3654
3730
|
revision: 1,
|
|
@@ -4076,7 +4152,11 @@ async function reconcileMembershipRenewal(db, input, now) {
|
|
|
4076
4152
|
membershipUpdate("networkMembership", id10, {
|
|
4077
4153
|
status: status2,
|
|
4078
4154
|
graceEndsAt,
|
|
4079
|
-
...paid ? {
|
|
4155
|
+
...paid ? {
|
|
4156
|
+
termStartedAt: start,
|
|
4157
|
+
termEndsAt: end,
|
|
4158
|
+
...membershipOfferingVersion(member.offeringSnapshot).seatPurchaseWindowCalendarMonths === void 0 ? { seatPurchaseEndsAt: end } : {}
|
|
4159
|
+
} : {},
|
|
4080
4160
|
revision: Number(member.revision) + 1,
|
|
4081
4161
|
updatedAt: now
|
|
4082
4162
|
}),
|
|
@@ -4378,10 +4458,11 @@ async function reserveNamedMembershipSeat(db, input, now) {
|
|
|
4378
4458
|
const id10 = (await membershipOfferIdForRequest({ ...input, requestId: "named_seat" })).replace(/^offer_/, "seat_");
|
|
4379
4459
|
let seat = await membershipLoad(db, "networkSeat", id10);
|
|
4380
4460
|
if (!seat) {
|
|
4381
|
-
|
|
4461
|
+
const offering = membershipOfferingVersion(member.offeringSnapshot), claimId = await recipientKey(input, email);
|
|
4462
|
+
const purchaseEndsAt = seatPurchaseDeadline(offering, member);
|
|
4463
|
+
if (!["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) || Number(member.refundedCents) !== 0 || now < Number(member.initialTermStartedAt) || now >= Number(member.termEndsAt) || now > purchaseEndsAt || !Number.isSafeInteger(purchaseEndsAt) || member.namedSeatId !== void 0) {
|
|
4382
4464
|
membershipFail("named_seat_purchase_unavailable");
|
|
4383
4465
|
}
|
|
4384
|
-
const offering = membershipOfferingVersion(member.offeringSnapshot), claimId = await recipientKey(input, email);
|
|
4385
4466
|
const attrs = {
|
|
4386
4467
|
id: id10,
|
|
4387
4468
|
...membershipScope(input),
|
|
@@ -4400,7 +4481,7 @@ async function reserveNamedMembershipSeat(db, input, now) {
|
|
|
4400
4481
|
status: "payment_pending",
|
|
4401
4482
|
preparedAt: now,
|
|
4402
4483
|
termEndsAt: member.termEndsAt,
|
|
4403
|
-
seatPurchaseEndsAt:
|
|
4484
|
+
seatPurchaseEndsAt: purchaseEndsAt,
|
|
4404
4485
|
offeringSnapshot: offering,
|
|
4405
4486
|
revision: 1,
|
|
4406
4487
|
createdAt: now,
|
|
@@ -4617,7 +4698,7 @@ async function confirmNamedMembershipSeatPayment(db, input, now) {
|
|
|
4617
4698
|
}
|
|
4618
4699
|
if (seat.purchasedAt === void 0) {
|
|
4619
4700
|
if (!["payment_processing", "payment_canceling"].includes(String(seat.status))) membershipFail("named_seat_payment_not_expected");
|
|
4620
|
-
const eligible = seat.status !== "payment_canceling" && ["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) && Number(member.refundedCents) === 0 && paidAt <=
|
|
4701
|
+
const eligible = seat.status !== "payment_canceling" && ["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) && Number(member.refundedCents) === 0 && paidAt <= seatPurchaseDeadline(membershipOfferingVersion(member.offeringSnapshot), member) && now < Number(member.termEndsAt);
|
|
4621
4702
|
const status2 = eligible ? "renewal_pending" : "refund_pending", effectId = `${seat.id}:${eligible ? "attach-renewal" : "refund"}`;
|
|
4622
4703
|
try {
|
|
4623
4704
|
await db.transact([
|
|
@@ -4969,15 +5050,16 @@ async function readNamedSeatOffer(db, input, now) {
|
|
|
4969
5050
|
const offering = membershipOfferingVersion(member.offeringSnapshot);
|
|
4970
5051
|
const seat = member.namedSeatId ? await membershipLoad(db, "networkSeat", String(member.namedSeatId)) : void 0;
|
|
4971
5052
|
if (seat) requireMembershipScope(seat, input);
|
|
5053
|
+
const purchaseEndsAt = seatPurchaseDeadline(offering, member);
|
|
4972
5054
|
const offer = {
|
|
4973
5055
|
membershipId: id10,
|
|
4974
5056
|
amountCents: offering.seatPriceCents,
|
|
4975
5057
|
currency: offering.currency,
|
|
4976
5058
|
interval: offering.interval,
|
|
4977
5059
|
termEndsAt: Number(member.termEndsAt),
|
|
4978
|
-
purchaseEndsAt
|
|
5060
|
+
purchaseEndsAt,
|
|
4979
5061
|
autoRenew: member.autoRenew === true,
|
|
4980
|
-
eligible: ["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) && member.refundedCents === 0 && now >= Number(member.initialTermStartedAt) && now < Number(member.termEndsAt) && now <=
|
|
5062
|
+
eligible: ["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status)) && member.refundedCents === 0 && now >= Number(member.initialTermStartedAt) && now < Number(member.termEndsAt) && now <= purchaseEndsAt && (!seat || ["payment_pending", "payment_processing"].includes(String(seat.status))),
|
|
4981
5063
|
...seat ? { seat: {
|
|
4982
5064
|
seatId: String(seat.id),
|
|
4983
5065
|
status: String(seat.status),
|
|
@@ -4985,7 +5067,7 @@ async function readNamedSeatOffer(db, input, now) {
|
|
|
4985
5067
|
recipientEmail: String(seat.recipientEmailNormalized)
|
|
4986
5068
|
} } : {}
|
|
4987
5069
|
};
|
|
4988
|
-
return { ...offer, digest: await namedSeatOfferDigest(offer) };
|
|
5070
|
+
return { ...offer, digest: await namedSeatOfferDigest(offer), purchaseWindowed: offering.seatPurchaseWindowCalendarMonths !== void 0 };
|
|
4989
5071
|
}
|
|
4990
5072
|
|
|
4991
5073
|
// src/membership-seat-invitation.ts
|
|
@@ -5470,7 +5552,7 @@ async function requestNamedSeatReservation(options) {
|
|
|
5470
5552
|
async function requestNamedSeatOffer(options) {
|
|
5471
5553
|
const result = await requestAuthority(options, "seat-offer", { applicationId: options.applicationId, skuId: options.skuId });
|
|
5472
5554
|
const offer = result.seat;
|
|
5473
|
-
if (!offer || offer.membershipId !== await networkMembershipId(options) || !Number.isSafeInteger(offer.amountCents) || offer.amountCents <= 0 || !/^[a-z]{3}$/.test(offer.currency) || !["month", "year"].includes(offer.interval) || typeof offer.eligible !== "boolean" || typeof offer.autoRenew !== "boolean" || !Number.isSafeInteger(offer.termEndsAt) || !Number.isSafeInteger(offer.purchaseEndsAt) || offer.digest !== await namedSeatOfferDigest(offer)) throw new Error("invalid named seat offer");
|
|
5555
|
+
if (!offer || offer.membershipId !== await networkMembershipId(options) || !Number.isSafeInteger(offer.amountCents) || offer.amountCents <= 0 || !/^[a-z]{3}$/.test(offer.currency) || !["month", "year"].includes(offer.interval) || typeof offer.eligible !== "boolean" || typeof offer.autoRenew !== "boolean" || !Number.isSafeInteger(offer.termEndsAt) || !Number.isSafeInteger(offer.purchaseEndsAt) || offer.purchaseWindowed !== void 0 && typeof offer.purchaseWindowed !== "boolean" || offer.digest !== await namedSeatOfferDigest(offer)) throw new Error("invalid named seat offer");
|
|
5474
5556
|
return offer;
|
|
5475
5557
|
}
|
|
5476
5558
|
async function requestNamedSeatInvitation(options) {
|
|
@@ -6554,6 +6636,12 @@ function planDelivery(input) {
|
|
|
6554
6636
|
}
|
|
6555
6637
|
|
|
6556
6638
|
// src/notify.ts
|
|
6639
|
+
function fromAddress(configured, name) {
|
|
6640
|
+
const display = name?.trim();
|
|
6641
|
+
if (!display) return configured;
|
|
6642
|
+
const angled = configured.match(/<([^>]+)>/);
|
|
6643
|
+
return { name: display, email: (angled ? angled[1] : configured).trim() };
|
|
6644
|
+
}
|
|
6557
6645
|
async function sendTemplated(deps, input) {
|
|
6558
6646
|
const { emailLog: emailLog2 } = await deps.db.query({ emailLog: { $: { where: { dedupeKey: input.dedupeKey } } } });
|
|
6559
6647
|
const prior = Array.isArray(emailLog2) ? emailLog2 : [];
|
|
@@ -6616,7 +6704,7 @@ async function sendTemplated(deps, input) {
|
|
|
6616
6704
|
let messageId;
|
|
6617
6705
|
try {
|
|
6618
6706
|
const response = await deps.sender.send({
|
|
6619
|
-
from: deps.from,
|
|
6707
|
+
from: fromAddress(deps.from, input.group.fromName),
|
|
6620
6708
|
to: [decision.to],
|
|
6621
6709
|
subject: String(row2.subject),
|
|
6622
6710
|
text: String(row2.body),
|
|
@@ -6649,6 +6737,7 @@ function emailGroupFrom(row2) {
|
|
|
6649
6737
|
name: String(row2.name ?? ""),
|
|
6650
6738
|
replyTo: str2(row2.replyTo) ?? "",
|
|
6651
6739
|
debugEmail: str2(row2.debugEmail),
|
|
6740
|
+
fromName: str2(row2.fromName),
|
|
6652
6741
|
refundPolicyText: str2(row2.refundPolicyText),
|
|
6653
6742
|
commitmentText: str2(row2.commitmentText),
|
|
6654
6743
|
normsText: str2(row2.normsText),
|
|
@@ -9415,6 +9504,7 @@ export {
|
|
|
9415
9504
|
CHAPTER_PROMOTION_ADAPTER,
|
|
9416
9505
|
DEFAULT_CHAPTER_COPY,
|
|
9417
9506
|
DEFAULT_SHARE_FIELDS,
|
|
9507
|
+
EDGE_UNPAIRED,
|
|
9418
9508
|
GIFT_OFFER_CATALOG_VERSION,
|
|
9419
9509
|
JOURNEY_ENDINGS,
|
|
9420
9510
|
JOURNEY_STAGES,
|
|
@@ -9495,6 +9585,7 @@ export {
|
|
|
9495
9585
|
defaultCrm,
|
|
9496
9586
|
defineChapter,
|
|
9497
9587
|
drainMembershipEffects,
|
|
9588
|
+
edgeUnpaired,
|
|
9498
9589
|
emailGroupFrom,
|
|
9499
9590
|
endForSlot,
|
|
9500
9591
|
exportChapterPromotion,
|
|
@@ -9554,6 +9645,7 @@ export {
|
|
|
9554
9645
|
normalizeSharedRecord,
|
|
9555
9646
|
normalizeWebhookEvent,
|
|
9556
9647
|
offerableTiers,
|
|
9648
|
+
pairingCommand,
|
|
9557
9649
|
paymentsReady,
|
|
9558
9650
|
personInputFromApp,
|
|
9559
9651
|
planDelivery,
|
|
@@ -9623,6 +9715,7 @@ export {
|
|
|
9623
9715
|
resolveSignupControl,
|
|
9624
9716
|
resolveTiers,
|
|
9625
9717
|
roleFromClaim,
|
|
9718
|
+
seatPurchaseDeadline,
|
|
9626
9719
|
sendTemplated,
|
|
9627
9720
|
sharedPersonInput,
|
|
9628
9721
|
sharedRecordFromCrm,
|