@odla-ai/chapter 0.33.2 → 0.34.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.cjs CHANGED
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ CHAPTER_PROMOTION_ADAPTER: () => CHAPTER_PROMOTION_ADAPTER,
23
24
  DEFAULT_CHAPTER_COPY: () => DEFAULT_CHAPTER_COPY,
24
25
  DEFAULT_SHARE_FIELDS: () => DEFAULT_SHARE_FIELDS,
25
26
  MEMBERSHIP_PAGE_RENDERER: () => MEMBERSHIP_PAGE_RENDERER,
@@ -61,6 +62,7 @@ __export(index_exports, {
61
62
  defineChapter: () => defineChapter,
62
63
  emailGroupFrom: () => emailGroupFrom,
63
64
  endForSlot: () => endForSlot,
65
+ exportChapterPromotion: () => exportChapterPromotion,
64
66
  findApplicationRef: () => findApplicationRef,
65
67
  findTier: () => findTier,
66
68
  firstPaymentPatch: () => firstPaymentPatch,
@@ -3200,4 +3202,95 @@ function membershipTierPresentationFromMarkdown(presentation, source) {
3200
3202
  if (!result.ok) throw new TypeError(`Invalid membership Markdown: ${result.errors.join("; ")}`);
3201
3203
  return result.value;
3202
3204
  }
3205
+
3206
+ // src/promotion.ts
3207
+ var import_promotion = require("@odla-ai/promotion");
3208
+ var CHAPTER_PROMOTION_ADAPTER = "@odla-ai/chapter/v1";
3209
+ var exclusions = (chapterId, paidTierIds) => [
3210
+ {
3211
+ kind: "chapter.providers",
3212
+ id: chapterId,
3213
+ reason: "provider_identity",
3214
+ paths: [
3215
+ ...paidTierIds.map((id2) => `tiers[${id2}].stripePriceId`),
3216
+ "groups.stripePublishableKey",
3217
+ "applications.stripeCustomerId",
3218
+ "applications.stripeSubscriptionId",
3219
+ "meetings.googleEventId"
3220
+ ],
3221
+ detail: "Stripe, Clerk, and Google identities are resolved independently in each target environment."
3222
+ },
3223
+ {
3224
+ kind: "chapter.runtime",
3225
+ id: chapterId,
3226
+ reason: "runtime_state",
3227
+ paths: ["applications.*", "meetings.*", "emailLog.*", "crm_*.*"],
3228
+ detail: "Applicants, meetings, messages, and CRM rows are operational state, not managed signup content."
3229
+ },
3230
+ {
3231
+ kind: "chapter.access",
3232
+ id: chapterId,
3233
+ reason: "personal_data",
3234
+ paths: ["admins.*", "superAdmins.*", "networkNotes.*"],
3235
+ detail: "People, access lists, and private network notes remain local to the target environment."
3236
+ },
3237
+ {
3238
+ kind: "chapter.history",
3239
+ id: chapterId,
3240
+ reason: "authority_history",
3241
+ paths: ["signupControls[active=false]", "signupControls.*At", "signupControls.environment"],
3242
+ detail: "The source retains immutable delivery history; only selected published content is exported."
3243
+ }
3244
+ ];
3245
+ async function exportChapterPromotion(input) {
3246
+ if (!/^sha256:[0-9a-f]{64}$/.test(input.digest)) throw new TypeError("chapter promotion digest is invalid");
3247
+ const checked = validateSignupControlDocument(input.document);
3248
+ if (!checked.ok) throw new TypeError(checked.errors.join("; "));
3249
+ const document = checked.value;
3250
+ if (await signupControlDigest(document) !== input.digest) throw new TypeError("chapter promotion digest does not match its document");
3251
+ const revision = `chapter:${document.target.chapterId}:${document.revision}`;
3252
+ const promotionProvenance = {
3253
+ adapter: CHAPTER_PROMOTION_ADAPTER,
3254
+ sourceIds: [`signup-control:${document.revision}`, document.source.appId, document.target.chapterId].sort(),
3255
+ receiptDigests: [input.digest]
3256
+ };
3257
+ const artifact = (kind, id2, content) => ({
3258
+ kind,
3259
+ id: id2,
3260
+ sourceRevision: revision,
3261
+ provenance: promotionProvenance,
3262
+ content: (0, import_promotion.canonicalPromotionValue)(content)
3263
+ });
3264
+ const chapterId = document.target.chapterId;
3265
+ const artifacts = [
3266
+ artifact("chapter.catalog", chapterId, {
3267
+ chapterId,
3268
+ tiers: document.tiers.map(({ stripePriceId: _providerId, ...tier }) => tier)
3269
+ }),
3270
+ artifact("chapter.membership-page", chapterId, document.membershipPage),
3271
+ ...document.application ? [artifact("chapter.application", chapterId, document.application)] : [],
3272
+ ...document.policy ? [artifact("chapter.policy", chapterId, document.policy)] : [],
3273
+ ...document.scheduling ? [artifact("chapter.scheduling", chapterId, document.scheduling)] : [],
3274
+ ...document.theme ? [artifact("chapter.theme", chapterId, document.theme)] : []
3275
+ ];
3276
+ return {
3277
+ adapter: CHAPTER_PROMOTION_ADAPTER,
3278
+ artifacts,
3279
+ exclusions: exclusions(chapterId, document.tiers.filter((tier) => tier.stripePriceId).map((tier) => tier.id)),
3280
+ preconditions: [
3281
+ {
3282
+ code: "chapter.signup-control.schema",
3283
+ path: "services.chapter.signupControl.schemaVersion",
3284
+ expected: document.schemaVersion,
3285
+ detail: "The target must support this Chapter signup-control document version."
3286
+ },
3287
+ {
3288
+ code: "chapter.identity",
3289
+ path: "app.appId",
3290
+ expected: chapterId,
3291
+ detail: "Chapter content can only target the chapter named by the signed source revision."
3292
+ }
3293
+ ]
3294
+ };
3295
+ }
3203
3296
  //# sourceMappingURL=index.cjs.map