@odla-ai/chapter 0.56.2 → 0.58.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/dist/index.js CHANGED
@@ -139,6 +139,7 @@ async function submitApplication(db, chapter, fields, opts) {
139
139
  clerkUserId: opts.namedSeat.userId,
140
140
  clerkAccountPending: false
141
141
  });
142
+ if (opts.predecessor?.clerkUserId && !opts.namedSeat) Object.assign(row2, { clerkUserId: opts.predecessor.clerkUserId, clerkAccountPending: false });
142
143
  if (typeof fields.email === "string" && isValidEmail(fields.email.trim())) {
143
144
  row2.emailNormalized = normalizeChapterEmail(fields.email);
144
145
  row2.signupEmailKey = row2.emailNormalized;
@@ -157,6 +158,8 @@ async function submitApplication(db, chapter, fields, opts) {
157
158
  }
158
159
  if (acked) row2.disclaimerAckAt = opts.now;
159
160
  const ops = [
161
+ // The unique signup key leaves the closed predecessor before the new attempt takes it.
162
+ ...opts.predecessor && opts.predecessor.id !== id11 ? [{ t: "retract", ns: "applications", id: opts.predecessor.id, attrs: ["signupEmailKey"] }] : [],
160
163
  { t: "update", ns: "applications", id: id11, attrs: row2 }
161
164
  ];
162
165
  if (opts.admissionGrant?.decision === "waive_interview") {
@@ -1093,7 +1096,7 @@ var DEFAULT_SCHEDULING = {
1093
1096
  endHour: 17,
1094
1097
  timezone: "America/Los_Angeles",
1095
1098
  minNoticeHours: 24,
1096
- windowDays: 14
1099
+ windowDays: 21
1097
1100
  };
1098
1101
  function defaultEmailTemplates(name) {
1099
1102
  const sign = `
@@ -1492,8 +1495,10 @@ var DEFAULT_ADMIN_COPY = {
1492
1495
  superAdminHint: "Super-admin, managed in odla Studio.",
1493
1496
  noAccount: "No linked account yet. The role is set once they sign in.",
1494
1497
  approve: "Approve",
1498
+ decline: "Decline",
1495
1499
  refund: "Refund",
1496
1500
  approved: "Approved.",
1501
+ declined: "Declined.",
1497
1502
  refunded: "Refund issued.",
1498
1503
  roleSet: "Role set to {role}.",
1499
1504
  messageSent: "Message sent.",
@@ -4273,7 +4278,7 @@ async function refundNetworkMembership(db, input, secretKey, now) {
4273
4278
  import { stripeRequest as stripeRequest4 } from "@odla-ai/stripe";
4274
4279
 
4275
4280
  // src/membership-seat-reservation.ts
4276
- async function recipientKey(input, email) {
4281
+ async function namedSeatRecipientClaimId(input, email) {
4277
4282
  const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(JSON.stringify([input.appId, input.chapterId, input.environment, input.runtime, email])));
4278
4283
  return `seat-recipient:${[...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("")}`;
4279
4284
  }
@@ -4290,7 +4295,7 @@ async function reserveNamedMembershipSeat(db, input, now) {
4290
4295
  const id11 = (await membershipOfferIdForRequest({ ...input, requestId: "named_seat" })).replace(/^offer_/, "seat_");
4291
4296
  let seat = await membershipLoad(db, "networkSeat", id11);
4292
4297
  if (!seat) {
4293
- const offering = membershipOfferingVersion(member.offeringSnapshot), claimId = await recipientKey(input, email);
4298
+ const offering = membershipOfferingVersion(member.offeringSnapshot), claimId = await namedSeatRecipientClaimId(input, email);
4294
4299
  const purchaseEndsAt = seatPurchaseDeadline(offering, member);
4295
4300
  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) {
4296
4301
  membershipFail("named_seat_purchase_unavailable");
@@ -5379,6 +5384,128 @@ async function refundNamedSeatByOperator(db, input, stripeSecretKey, now) {
5379
5384
  return { seatId: String(seat.id), status: "refunded", refundedCents: Number(refunded.refundedCents), subscriptionCanceled: false };
5380
5385
  }
5381
5386
 
5387
+ // src/membership-effect-kinds.ts
5388
+ var MEMBERSHIP_CHAPTER_EFFECT_KINDS = [
5389
+ "invite_named_recipient",
5390
+ "grant_named_recipient_access",
5391
+ "revoke_named_recipient_access",
5392
+ "release_named_recipient"
5393
+ ];
5394
+ var namedSeatInvitationOpen = (member) => ["active", "cancel_at_term_end"].includes(String(member.status)) && Number.isSafeInteger(member.journeyApprovedAt);
5395
+
5396
+ // src/membership-seat-regift.ts
5397
+ var REGIFTABLE_SEAT_STATUSES = ["pending_acceptance", "pending_approval", "pending_primary"];
5398
+ var namedSeatRegiftable = (seat) => REGIFTABLE_SEAT_STATUSES.includes(String(seat.status));
5399
+ var receiptFor = (seat, released) => ({
5400
+ seatId: String(seat.id),
5401
+ status: "pending_acceptance",
5402
+ recipientName: String(seat.recipientName),
5403
+ recipientEmail: String(seat.recipientEmailNormalized),
5404
+ regiftedAt: Number(seat.regiftedAt),
5405
+ releasedRecipientApplicationId: released
5406
+ });
5407
+ async function regiftNamedSeat(db, input, now) {
5408
+ membershipClock(now);
5409
+ const name = typeof input.recipientName === "string" ? input.recipientName.trim().replace(/\s+/g, " ") : "";
5410
+ const email = normalizeChapterEmail(typeof input.recipientEmail === "string" ? input.recipientEmail : "");
5411
+ if (name.length < 2 || name.length > 160 || /[\u0000-\u001f\u007f]/.test(input.recipientName) || email.length > 254 || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) membershipFail("invalid_named_seat_recipient");
5412
+ const state = await loadMembershipAuthorityState(db, input);
5413
+ const seat = await membershipLoad(db, "networkSeat", input.seatId);
5414
+ requireMembershipScope(seat, input);
5415
+ const member = await membershipLoad(db, "networkMembership", String(seat.primaryMembershipId));
5416
+ requireMembershipScope(member, input);
5417
+ if (member.namedSeatId !== seat.id) membershipFail("named_seat_primary_conflict");
5418
+ if (typeof seat.purchaserEmailNormalized === "string" && seat.purchaserEmailNormalized === email) membershipFail("invalid_named_seat_recipient");
5419
+ const history = Array.isArray(seat.formerRecipients) ? seat.formerRecipients : [];
5420
+ if (seat.recipientEmailNormalized === email && seat.recipientName === name && seat.regiftedAt !== void 0 && seat.status === "pending_acceptance") {
5421
+ return receiptFor(seat, history.at(-1)?.recipientApplicationId ?? null);
5422
+ }
5423
+ if (!namedSeatRegiftable(seat)) membershipFail("named_seat_not_regiftable");
5424
+ if (seat.recipientEmailNormalized === email) membershipFail("named_seat_recipient_unchanged");
5425
+ const entitlement = await membershipLoad(db, "networkEntitlement", String(seat.entitlementId));
5426
+ requireMembershipScope(entitlement, input);
5427
+ const claimId = await namedSeatRecipientClaimId(input, email);
5428
+ const former = {
5429
+ recipientName: String(seat.recipientName),
5430
+ recipientEmail: String(seat.recipientEmailNormalized),
5431
+ recipientClaimId: String(seat.recipientClaimId),
5432
+ releasedAt: now,
5433
+ ...typeof seat.recipientUserId === "string" ? { recipientUserId: seat.recipientUserId } : {},
5434
+ ...typeof seat.recipientApplicationId === "string" ? { recipientApplicationId: seat.recipientApplicationId } : {},
5435
+ ...Number.isSafeInteger(seat.acceptedAt) ? { acceptedAt: Number(seat.acceptedAt) } : {},
5436
+ ...Number.isSafeInteger(seat.journeyApprovedAt) ? { journeyApprovedAt: Number(seat.journeyApprovedAt) } : {}
5437
+ };
5438
+ const generation = history.length + 1, inviteId = `${seat.id}:invite:${generation}`, releaseId = `${seat.id}:release:${generation}`;
5439
+ const bound = Boolean(former.recipientUserId && former.recipientApplicationId);
5440
+ const stale = ((await db.query({ membershipEffect: { $: { where: { seatId: seat.id, kind: "invite_named_recipient", status: "pending" }, limit: 10 } } })).membershipEffect ?? []).filter((row2) => row2.chapterId === input.chapterId && row2.environment === input.environment && row2.runtime === input.runtime);
5441
+ const cleared = ["recipientUserId", "recipientApplicationId", "acceptedAt", "journeyApprovedAt"];
5442
+ const effect = (id11, kind, extra = {}) => membershipUpdate("membershipEffect", id11, {
5443
+ id: id11,
5444
+ chapterId: input.chapterId,
5445
+ environment: input.environment,
5446
+ runtime: input.runtime,
5447
+ membershipId: member.id,
5448
+ seatId: seat.id,
5449
+ kind,
5450
+ status: "pending",
5451
+ attempts: 0,
5452
+ createdAt: now,
5453
+ updatedAt: now,
5454
+ ...extra
5455
+ });
5456
+ const ops = [
5457
+ membershipUpdate("networkSeat", String(seat.id), {
5458
+ recipientName: name,
5459
+ recipientEmailNormalized: email,
5460
+ recipientClaimId: claimId,
5461
+ status: "pending_acceptance",
5462
+ regiftedAt: now,
5463
+ formerRecipients: [...history, former],
5464
+ revision: Number(seat.revision) + 1,
5465
+ updatedAt: now
5466
+ }),
5467
+ { t: "retract", ns: "networkSeat", id: String(seat.id), attrs: cleared },
5468
+ membershipUpdate("networkEntitlement", String(entitlement.id), { status: "pending_acceptance", revision: Number(entitlement.revision) + 1, updatedAt: now }),
5469
+ { t: "retract", ns: "networkEntitlement", id: String(entitlement.id), attrs: cleared },
5470
+ { t: "delete", ns: "networkSeatRecipient", id: String(seat.recipientClaimId) },
5471
+ membershipUpdate("networkSeatRecipient", claimId, {
5472
+ id: claimId,
5473
+ appId: input.appId,
5474
+ chapterId: input.chapterId,
5475
+ environment: input.environment,
5476
+ runtime: input.runtime,
5477
+ seatId: seat.id,
5478
+ recipientEmailNormalized: email,
5479
+ createdAt: now
5480
+ }),
5481
+ ...stale.map((row2) => membershipUpdate("membershipEffect", String(row2.id), { status: "complete", updatedAt: now })),
5482
+ effect(inviteId, "invite_named_recipient"),
5483
+ ...bound ? [effect(releaseId, "release_named_recipient", { recipientUserId: former.recipientUserId, recipientApplicationId: former.recipientApplicationId })] : []
5484
+ ];
5485
+ try {
5486
+ await db.transact(ops, { mutationId: `named-seat-regift:${seat.id}:${generation}`, guards: [
5487
+ { ns: "networkSeat", id: String(seat.id), exists: true, equals: { revision: seat.revision, status: seat.status } },
5488
+ { ns: "networkEntitlement", id: String(entitlement.id), exists: true, equals: { revision: entitlement.revision } },
5489
+ { ns: "networkMembership", id: String(member.id), exists: true, equals: { revision: member.revision, namedSeatId: seat.id } },
5490
+ { ns: "networkSeatRecipient", id: claimId, exists: false },
5491
+ ...stale.map((row2) => ({ ns: "membershipEffect", id: String(row2.id), exists: true, equals: { status: "pending" } })),
5492
+ { ns: "membershipAuthorityState", id: String(state.id), exists: true, equals: { mode: "authoritative", revision: state.revision } }
5493
+ ] });
5494
+ } catch (error) {
5495
+ if (error.code !== "transact_guard_failed") throw error;
5496
+ const current = await membershipLoad(db, "networkSeat", input.seatId);
5497
+ requireMembershipScope(current, input);
5498
+ if (current.recipientEmailNormalized === email && current.status === "pending_acceptance") return receiptFor(current, former.recipientApplicationId ?? null);
5499
+ const claim = await membershipLoad(db, "networkSeatRecipient", claimId);
5500
+ if (claim && claim.seatId !== seat.id) membershipFail("named_seat_recipient_unavailable");
5501
+ membershipFail("named_seat_regift_retry_required");
5502
+ }
5503
+ const saved = await membershipLoad(db, "networkSeat", input.seatId);
5504
+ requireMembershipScope(saved, input);
5505
+ if (saved.recipientEmailNormalized !== email || saved.status !== "pending_acceptance") membershipFail("named_seat_regift_retry_required");
5506
+ return receiptFor(saved, former.recipientApplicationId ?? null);
5507
+ }
5508
+
5382
5509
  // src/membership-seat-offer.ts
5383
5510
  async function namedSeatOfferDigest(offer) {
5384
5511
  const bytes = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(JSON.stringify([
@@ -5422,7 +5549,10 @@ async function readNamedSeatOffer(db, input, now) {
5422
5549
  recipientState: namedSeatRecipientState(seat),
5423
5550
  ...at(seat.purchasedAt) !== void 0 ? { purchasedAt: at(seat.purchasedAt) } : {},
5424
5551
  ...at(seat.acceptedAt) !== void 0 ? { acceptedAt: at(seat.acceptedAt) } : {},
5425
- ...seat.status === "active" && at(seat.journeyApprovedAt) !== void 0 ? { joinedAt: at(seat.journeyApprovedAt) } : {}
5552
+ ...seat.status === "active" && at(seat.journeyApprovedAt) !== void 0 ? { joinedAt: at(seat.journeyApprovedAt) } : {},
5553
+ ...seat.status === "pending_acceptance" && seat.acceptedAt === void 0 && !namedSeatInvitationOpen(member) ? { invitationHeld: true } : {},
5554
+ ...namedSeatRegiftable(seat) ? { regiftable: true } : {},
5555
+ ...at(seat.regiftedAt) !== void 0 ? { regiftedAt: at(seat.regiftedAt) } : {}
5426
5556
  } } : {}
5427
5557
  };
5428
5558
  return {
@@ -5470,10 +5600,14 @@ async function readMembershipChapterEffect(db, input, now) {
5470
5600
  requireMembershipScope(seat, input);
5471
5601
  const member = await membershipLoad(db, "networkMembership", String(seat.primaryMembershipId));
5472
5602
  requireMembershipScope(member, input);
5473
- if (!effect || effect.kind !== input.kind || effect.seatId !== seat.id || effect.membershipId !== member.id || ["chapterId", "environment", "runtime"].some((key3) => effect[key3] !== seat[key3]) || !["invite_named_recipient", "grant_named_recipient_access", "revoke_named_recipient_access"].includes(input.kind)) throw new Error("invalid chapter effect");
5603
+ if (!effect || effect.kind !== input.kind || effect.seatId !== seat.id || effect.membershipId !== member.id || ["chapterId", "environment", "runtime"].some((key3) => effect[key3] !== seat[key3]) || !MEMBERSHIP_CHAPTER_EFFECT_KINDS.includes(input.kind)) throw new Error("invalid chapter effect");
5604
+ const released = input.kind === "release_named_recipient";
5605
+ const recipientUserId = released ? effect.recipientUserId : seat.recipientUserId;
5606
+ const recipientApplicationId = released ? effect.recipientApplicationId : seat.recipientApplicationId;
5474
5607
  let applicable;
5475
- if (input.kind === "invite_named_recipient") applicable = seat.status === "pending_acceptance" && seat.acceptedAt === void 0 && now < Number(member.termEndsAt) && ["paid_pending_approval", "active", "cancel_at_term_end"].includes(String(member.status));
5608
+ if (input.kind === "invite_named_recipient") applicable = seat.status === "pending_acceptance" && seat.acceptedAt === void 0 && now < Number(member.termEndsAt) && namedSeatInvitationOpen(member);
5476
5609
  else if (input.kind === "revoke_named_recipient_access") applicable = ["refund_pending", "refunded"].includes(String(seat.status));
5610
+ else if (released) applicable = typeof recipientApplicationId === "string" && seat.recipientApplicationId !== recipientApplicationId;
5477
5611
  else applicable = (await readNamedSeatAccess(db, {
5478
5612
  ...input,
5479
5613
  recipientUserId: String(seat.recipientUserId),
@@ -5483,8 +5617,8 @@ async function readMembershipChapterEffect(db, input, now) {
5483
5617
  ...input,
5484
5618
  recipientName: String(seat.recipientName),
5485
5619
  recipientEmail: String(seat.recipientEmailNormalized),
5486
- recipientUserId: typeof seat.recipientUserId === "string" ? seat.recipientUserId : null,
5487
- recipientApplicationId: typeof seat.recipientApplicationId === "string" ? seat.recipientApplicationId : null,
5620
+ recipientUserId: typeof recipientUserId === "string" ? recipientUserId : null,
5621
+ recipientApplicationId: typeof recipientApplicationId === "string" ? recipientApplicationId : null,
5488
5622
  acceptanceEndsAt: Number(seat.acceptanceEndsAt),
5489
5623
  termEndsAt: Number(seat.termEndsAt),
5490
5624
  applicable
@@ -5505,7 +5639,8 @@ var MEMBERSHIP_SEAT_ACTION_FIELDS = {
5505
5639
  "seat-accept": recipient,
5506
5640
  "seat-approve": recipient,
5507
5641
  "seat-decline": recipient,
5508
- "seat-effect": ["seatId", "effectId", "kind"]
5642
+ "seat-effect": ["seatId", "effectId", "kind"],
5643
+ "seat-regift": ["seatId", "recipientName", "recipientEmail"]
5509
5644
  };
5510
5645
  async function handleMembershipSeatAction(action, db, peer, input, now, stripeSecretName) {
5511
5646
  if (!peer.seatPriceId) throw new Error("named seats are not configured");
@@ -5530,6 +5665,12 @@ async function handleMembershipSeatAction(action, db, peer, input, now, stripeSe
5530
5665
  kind: String(input.kind)
5531
5666
  }, now);
5532
5667
  if (action === "seat-offer") return readNamedSeatOffer(db, target, now);
5668
+ if (action === "seat-regift") return regiftNamedSeat(db, {
5669
+ ...target,
5670
+ seatId: String(input.seatId),
5671
+ recipientName: String(input.recipientName),
5672
+ recipientEmail: String(input.recipientEmail)
5673
+ }, now);
5533
5674
  if (action === "seat-reservations") {
5534
5675
  const seat = await reserveNamedMembershipSeat(db, {
5535
5676
  ...target,
@@ -5907,6 +6048,18 @@ async function requestNamedSeatOperatorRefund(options) {
5907
6048
  if (!seat || seat.seatId !== options.seatId || seat.status !== "refunded" || seat.subscriptionCanceled !== false || !Number.isSafeInteger(seat.refundedCents) || seat.refundedCents < 0) throw new Error("invalid named seat refund receipt");
5908
6049
  return seat;
5909
6050
  }
6051
+ async function requestNamedSeatRegift(options) {
6052
+ const result = await requestAuthority(options, "seat-regift", {
6053
+ applicationId: options.applicationId,
6054
+ skuId: options.skuId,
6055
+ seatId: options.seatId,
6056
+ recipientName: options.recipientName,
6057
+ recipientEmail: options.recipientEmail
6058
+ });
6059
+ const seat = result.seat;
6060
+ if (!seat || seat.seatId !== options.seatId || seat.status !== "pending_acceptance" || typeof seat.recipientName !== "string" || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(String(seat.recipientEmail)) || !Number.isSafeInteger(seat.regiftedAt) || seat.releasedRecipientApplicationId !== null && typeof seat.releasedRecipientApplicationId !== "string") throw new Error("invalid named seat regift receipt");
6061
+ return seat;
6062
+ }
5910
6063
  async function requestNamedSeatReservation(options) {
5911
6064
  const result = await requestAuthority(options, "seat-reservations", {
5912
6065
  applicationId: options.applicationId,
@@ -6152,7 +6305,7 @@ async function drainMembershipEffects(db, options, now) {
6152
6305
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 100 || !options.stripeSecretKey) throw new TypeError("invalid membership recovery configuration");
6153
6306
  await loadMembershipAuthorityState(db, scope2);
6154
6307
  const matches2 = (row2) => Object.entries(scope2).every(([key3, value]) => row2[key3] === value);
6155
- let pending = 0, complete = 0, more = false;
6308
+ let pending = 0, complete = 0, held = 0, more = false;
6156
6309
  for (const status2 of ["payment_pending", "payment_processing", "payment_canceling"]) {
6157
6310
  const seats = (await db.query({ networkSeat: { $: { where: { ...scope2, status: status2 }, order: { updatedAt: "asc" }, limit: limit + 1 } } })).networkSeat ?? [];
6158
6311
  more ||= seats.length > limit;
@@ -6188,6 +6341,10 @@ async function drainMembershipEffects(db, options, now) {
6188
6341
  requireMembershipScope(seat, target);
6189
6342
  if (seat.primaryMembershipId !== member.id) throw new Error("membership seat scope mismatch");
6190
6343
  }
6344
+ if (effect.kind === "invite_named_recipient" && seat?.acceptedAt === void 0 && !namedSeatInvitationOpen(member) && !["refund_pending", "refunded"].includes(String(seat?.status))) {
6345
+ held++;
6346
+ continue;
6347
+ }
6191
6348
  try {
6192
6349
  const attempts = Number(effect.attempts);
6193
6350
  if (!Number.isSafeInteger(attempts) || attempts < 0) throw new Error("invalid membership effect attempt");
@@ -6211,9 +6368,10 @@ async function drainMembershipEffects(db, options, now) {
6211
6368
  break;
6212
6369
  case "invite_named_recipient":
6213
6370
  case "grant_named_recipient_access":
6214
- case "revoke_named_recipient_access": {
6371
+ case "revoke_named_recipient_access":
6372
+ case "release_named_recipient": {
6215
6373
  if (!seat) throw new Error("named seat effect missing seat");
6216
- if (effect.kind !== "revoke_named_recipient_access" && ["refund_pending", "refunded"].includes(String(seat.status))) break;
6374
+ if (["invite_named_recipient", "grant_named_recipient_access"].includes(String(effect.kind)) && ["refund_pending", "refunded"].includes(String(seat.status))) break;
6217
6375
  if (!options.deliverChapterEffect) throw new Error("chapter effect receiver unavailable");
6218
6376
  const receipt = await options.deliverChapterEffect({ ...target, effectId: String(effect.id), seatId: String(effect.seatId), kind: effect.kind });
6219
6377
  if (receipt.effectId !== effect.id || receipt.complete !== true) throw new Error("chapter effect receipt unconfirmed");
@@ -6231,7 +6389,7 @@ async function drainMembershipEffects(db, options, now) {
6231
6389
  pending++;
6232
6390
  }
6233
6391
  }
6234
- return { complete, pending, more };
6392
+ return { complete, pending, held, more };
6235
6393
  }
6236
6394
 
6237
6395
  // src/schema-membership-offers.ts
@@ -6401,7 +6559,9 @@ var membershipAuthorityEntities = {
6401
6559
  ...times(),
6402
6560
  refundReason: attr9("string", true),
6403
6561
  refundedCents: attr9("number", true),
6404
- providerRefundIds: attr9("json", true)
6562
+ providerRefundIds: attr9("json", true),
6563
+ regiftedAt: attr9("number", true),
6564
+ formerRecipients: attr9("json", true)
6405
6565
  } },
6406
6566
  networkSeatRecipient: { attrs: { id: id10(), appId: key2(), chapterId: key2(), environment: key2(), runtime: key2(), seatId: key2(), recipientEmailNormalized: key2(), createdAt: attr9("number") } },
6407
6567
  membershipEffect: { attrs: {
@@ -6416,6 +6576,8 @@ var membershipAuthorityEntities = {
6416
6576
  attempts: attr9("number"),
6417
6577
  providerObjectId: key2(true),
6418
6578
  error: attr9("string", true),
6579
+ recipientUserId: key2(true),
6580
+ recipientApplicationId: key2(true),
6419
6581
  createdAt: attr9("number"),
6420
6582
  updatedAt: attr9("number", false, false, true)
6421
6583
  } }
@@ -8717,7 +8879,7 @@ var SCHEDULING_DEFAULTS = {
8717
8879
  endHour: 17,
8718
8880
  timezone: "America/Los_Angeles",
8719
8881
  minNoticeHours: 24,
8720
- windowDays: 14,
8882
+ windowDays: 21,
8721
8883
  summaryTemplate: "Introduction call with {{firstName}} {{lastName}}"
8722
8884
  };
8723
8885
  function isValidTimeZone(tz) {
@@ -10220,6 +10382,7 @@ export {
10220
10382
  requestNamedSeatOperatorRefund,
10221
10383
  requestNamedSeatPayment,
10222
10384
  requestNamedSeatRefund2 as requestNamedSeatRefund,
10385
+ requestNamedSeatRegift,
10223
10386
  requestNamedSeatReservation,
10224
10387
  resolveApplication,
10225
10388
  resolveAuth,