@odla-ai/chapter 0.43.2 → 0.44.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/{copy-context-Bh1EZvCg.d.ts → copy-context-B4SCy6vx.d.ts} +18 -0
- package/dist/index.cjs +214 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +214 -102
- package/dist/index.js.map +1 -1
- package/dist/ui/admin/index.d.ts +2 -2
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/member/index.d.ts +2 -2
- package/dist/worker/index.cjs +651 -60
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +18 -0
- package/dist/worker/index.d.ts +18 -0
- package/dist/worker/index.js +651 -60
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -115,8 +115,8 @@ async function submitApplication(db, chapter, fields, opts) {
|
|
|
115
115
|
if (app.requireDisclaimerAck && !acked) {
|
|
116
116
|
return { ok: false, error: "disclaimerAck is required" };
|
|
117
117
|
}
|
|
118
|
-
const
|
|
119
|
-
const row = { id:
|
|
118
|
+
const id5 = opts.submissionId ? await applicationIdForSubmission(opts.submissionId) : opts.newId();
|
|
119
|
+
const row = { id: id5, status: chapter.pipeline.initial, createdAt: opts.now };
|
|
120
120
|
for (const f of [...app.required, ...app.optional]) {
|
|
121
121
|
if (fieldStates[f]?.visible === false) continue;
|
|
122
122
|
if (typeof fields[f] === "string") row[f] = fields[f].trim();
|
|
@@ -140,19 +140,19 @@ async function submitApplication(db, chapter, fields, opts) {
|
|
|
140
140
|
}
|
|
141
141
|
if (acked) row.disclaimerAckAt = opts.now;
|
|
142
142
|
const ops = [
|
|
143
|
-
{ t: "update", ns: "applications", id:
|
|
143
|
+
{ t: "update", ns: "applications", id: id5, attrs: row }
|
|
144
144
|
];
|
|
145
145
|
if (opts.admissionGrant?.decision === "waive_interview") {
|
|
146
146
|
ops.push({ t: "update", ns: "admissionGrants", id: opts.admissionGrant.id, attrs: {
|
|
147
147
|
consumedAt: opts.now,
|
|
148
|
-
consumedApplicationId:
|
|
148
|
+
consumedApplicationId: id5
|
|
149
149
|
} });
|
|
150
150
|
}
|
|
151
151
|
const { duplicate } = await db.transact(
|
|
152
152
|
ops,
|
|
153
153
|
opts.submissionId ? { mutationId: `join:${opts.submissionId}` } : void 0
|
|
154
154
|
);
|
|
155
|
-
return { ok: true, id:
|
|
155
|
+
return { ok: true, id: id5, duplicate, status: chapter.pipeline.initial, disclaimerAckAt: acked ? opts.now : null };
|
|
156
156
|
}
|
|
157
157
|
function joinConfig(group, paymentsReady2, tiers2 = [], conditions = {}) {
|
|
158
158
|
return {
|
|
@@ -466,6 +466,88 @@ var stripeEventReceiptsEntity = {
|
|
|
466
466
|
}
|
|
467
467
|
};
|
|
468
468
|
|
|
469
|
+
// src/schema-network-person.ts
|
|
470
|
+
var string = (flags = {}) => ({
|
|
471
|
+
type: "string",
|
|
472
|
+
unique: flags.unique ?? false,
|
|
473
|
+
indexed: flags.indexed ?? false,
|
|
474
|
+
optional: flags.optional ?? false
|
|
475
|
+
});
|
|
476
|
+
var number = (flags = {}) => ({
|
|
477
|
+
type: "number",
|
|
478
|
+
unique: false,
|
|
479
|
+
indexed: flags.indexed ?? false,
|
|
480
|
+
optional: flags.optional ?? false
|
|
481
|
+
});
|
|
482
|
+
var json = (flags = {}) => ({
|
|
483
|
+
type: "json",
|
|
484
|
+
unique: false,
|
|
485
|
+
indexed: false,
|
|
486
|
+
optional: flags.optional ?? false
|
|
487
|
+
});
|
|
488
|
+
var id3 = () => string({ unique: true, indexed: true });
|
|
489
|
+
var networkPersonsEntity = { attrs: {
|
|
490
|
+
id: id3(),
|
|
491
|
+
displayName: string({ indexed: true }),
|
|
492
|
+
state: string({ indexed: true }),
|
|
493
|
+
mergedIntoId: string({ indexed: true, optional: true }),
|
|
494
|
+
contactPolicy: json(),
|
|
495
|
+
revision: number({ indexed: true }),
|
|
496
|
+
createdAt: number({ indexed: true }),
|
|
497
|
+
updatedAt: number({ indexed: true })
|
|
498
|
+
} };
|
|
499
|
+
var networkIdentityClaimsEntity = { attrs: {
|
|
500
|
+
id: id3(),
|
|
501
|
+
personId: string({ indexed: true }),
|
|
502
|
+
kind: string({ indexed: true }),
|
|
503
|
+
value: string(),
|
|
504
|
+
hint: string({ optional: true }),
|
|
505
|
+
verifiedAt: number({ indexed: true }),
|
|
506
|
+
createdAt: number({ indexed: true })
|
|
507
|
+
} };
|
|
508
|
+
var networkPersonAliasesEntity = { attrs: {
|
|
509
|
+
id: id3(),
|
|
510
|
+
sourceSystem: string({ indexed: true }),
|
|
511
|
+
sourceRecordId: string({ indexed: true }),
|
|
512
|
+
sourceKey: string({ unique: true, indexed: true }),
|
|
513
|
+
displayName: string({ indexed: true }),
|
|
514
|
+
provenance: string(),
|
|
515
|
+
consent: json(),
|
|
516
|
+
status: string({ indexed: true }),
|
|
517
|
+
personId: string({ indexed: true, optional: true }),
|
|
518
|
+
candidatePersonIds: json({ optional: true }),
|
|
519
|
+
identityClaims: json(),
|
|
520
|
+
chapterLinks: json(),
|
|
521
|
+
revision: number({ indexed: true }),
|
|
522
|
+
createdAt: number({ indexed: true }),
|
|
523
|
+
updatedAt: number({ indexed: true })
|
|
524
|
+
} };
|
|
525
|
+
var networkChapterPersonLinksEntity = { attrs: {
|
|
526
|
+
id: id3(),
|
|
527
|
+
personId: string({ indexed: true }),
|
|
528
|
+
chapterId: string({ indexed: true }),
|
|
529
|
+
chapterPersonId: string({ indexed: true }),
|
|
530
|
+
state: string({ indexed: true }),
|
|
531
|
+
createdAt: number({ indexed: true })
|
|
532
|
+
} };
|
|
533
|
+
var networkPersonEventsEntity = { attrs: {
|
|
534
|
+
id: id3(),
|
|
535
|
+
kind: string({ indexed: true }),
|
|
536
|
+
personId: string({ indexed: true, optional: true }),
|
|
537
|
+
aliasId: string({ indexed: true, optional: true }),
|
|
538
|
+
actorId: string({ indexed: true }),
|
|
539
|
+
mutationId: string({ unique: true, indexed: true }),
|
|
540
|
+
detail: json(),
|
|
541
|
+
createdAt: number({ indexed: true })
|
|
542
|
+
} };
|
|
543
|
+
var networkPersonEntities = {
|
|
544
|
+
networkPersons: networkPersonsEntity,
|
|
545
|
+
networkIdentityClaims: networkIdentityClaimsEntity,
|
|
546
|
+
networkPersonAliases: networkPersonAliasesEntity,
|
|
547
|
+
networkChapterPersonLinks: networkChapterPersonLinksEntity,
|
|
548
|
+
networkPersonEvents: networkPersonEventsEntity
|
|
549
|
+
};
|
|
550
|
+
|
|
469
551
|
// src/schema.ts
|
|
470
552
|
function attr5(type, flags = {}) {
|
|
471
553
|
return {
|
|
@@ -475,10 +557,10 @@ function attr5(type, flags = {}) {
|
|
|
475
557
|
optional: flags.optional ?? false
|
|
476
558
|
};
|
|
477
559
|
}
|
|
478
|
-
var
|
|
560
|
+
var id4 = () => attr5("string", { unique: true, indexed: true });
|
|
479
561
|
var admins = {
|
|
480
562
|
attrs: {
|
|
481
|
-
id:
|
|
563
|
+
id: id4(),
|
|
482
564
|
email: attr5("string", { unique: true, indexed: true }),
|
|
483
565
|
name: attr5("string", { optional: true }),
|
|
484
566
|
note: attr5("string", { optional: true })
|
|
@@ -486,7 +568,7 @@ var admins = {
|
|
|
486
568
|
};
|
|
487
569
|
var superAdmins = {
|
|
488
570
|
attrs: {
|
|
489
|
-
id:
|
|
571
|
+
id: id4(),
|
|
490
572
|
email: attr5("string", { unique: true, indexed: true }),
|
|
491
573
|
note: attr5("string", { optional: true }),
|
|
492
574
|
createdAt: attr5("number", { indexed: true })
|
|
@@ -494,7 +576,7 @@ var superAdmins = {
|
|
|
494
576
|
};
|
|
495
577
|
var networkNotes = {
|
|
496
578
|
attrs: {
|
|
497
|
-
id:
|
|
579
|
+
id: id4(),
|
|
498
580
|
recordKey: attr5("string", { indexed: true }),
|
|
499
581
|
targetId: attr5("string", { indexed: true }),
|
|
500
582
|
recordType: attr5("string", { indexed: true }),
|
|
@@ -507,7 +589,7 @@ var networkNotes = {
|
|
|
507
589
|
};
|
|
508
590
|
var signupControls = {
|
|
509
591
|
attrs: {
|
|
510
|
-
id:
|
|
592
|
+
id: id4(),
|
|
511
593
|
sourceId: attr5("string", { indexed: true }),
|
|
512
594
|
targetId: attr5("string", { indexed: true }),
|
|
513
595
|
environment: attr5("string", { indexed: true }),
|
|
@@ -520,7 +602,7 @@ var signupControls = {
|
|
|
520
602
|
};
|
|
521
603
|
var memberContentControls = {
|
|
522
604
|
attrs: {
|
|
523
|
-
id:
|
|
605
|
+
id: id4(),
|
|
524
606
|
sourceId: attr5("string", { indexed: true }),
|
|
525
607
|
targetId: attr5("string", { indexed: true }),
|
|
526
608
|
environment: attr5("string", { indexed: true }),
|
|
@@ -533,7 +615,7 @@ var memberContentControls = {
|
|
|
533
615
|
};
|
|
534
616
|
var memberContentLocal = {
|
|
535
617
|
attrs: {
|
|
536
|
-
id:
|
|
618
|
+
id: id4(),
|
|
537
619
|
chapterId: attr5("string", { indexed: true }),
|
|
538
620
|
environment: attr5("string", { indexed: true }),
|
|
539
621
|
revision: attr5("number", { indexed: true }),
|
|
@@ -544,7 +626,7 @@ var memberContentLocal = {
|
|
|
544
626
|
};
|
|
545
627
|
var builderLibraryControls = {
|
|
546
628
|
attrs: {
|
|
547
|
-
id:
|
|
629
|
+
id: id4(),
|
|
548
630
|
sourceId: attr5("string", { indexed: true }),
|
|
549
631
|
targetId: attr5("string", { indexed: true }),
|
|
550
632
|
environment: attr5("string", { indexed: true }),
|
|
@@ -557,7 +639,7 @@ var builderLibraryControls = {
|
|
|
557
639
|
};
|
|
558
640
|
var builderLibraryLocal = {
|
|
559
641
|
attrs: {
|
|
560
|
-
id:
|
|
642
|
+
id: id4(),
|
|
561
643
|
appId: attr5("string", { indexed: true }),
|
|
562
644
|
environment: attr5("string", { indexed: true }),
|
|
563
645
|
revision: attr5("number", { indexed: true }),
|
|
@@ -568,7 +650,7 @@ var builderLibraryLocal = {
|
|
|
568
650
|
};
|
|
569
651
|
var groups = {
|
|
570
652
|
attrs: {
|
|
571
|
-
id:
|
|
653
|
+
id: id4(),
|
|
572
654
|
name: attr5("string"),
|
|
573
655
|
standardPriceCents: attr5("number"),
|
|
574
656
|
foundingDiscountCents: attr5("number"),
|
|
@@ -591,7 +673,7 @@ var groups = {
|
|
|
591
673
|
};
|
|
592
674
|
var tiers = {
|
|
593
675
|
attrs: {
|
|
594
|
-
id:
|
|
676
|
+
id: id4(),
|
|
595
677
|
groupId: attr5("string", { indexed: true }),
|
|
596
678
|
name: attr5("string"),
|
|
597
679
|
priceCents: attr5("number"),
|
|
@@ -604,7 +686,7 @@ var tiers = {
|
|
|
604
686
|
};
|
|
605
687
|
var meetings = {
|
|
606
688
|
attrs: {
|
|
607
|
-
id:
|
|
689
|
+
id: id4(),
|
|
608
690
|
applicationId: attr5("string", { indexed: true }),
|
|
609
691
|
groupId: attr5("string", { indexed: true }),
|
|
610
692
|
startAt: attr5("number", { indexed: true }),
|
|
@@ -623,7 +705,7 @@ var meetings = {
|
|
|
623
705
|
};
|
|
624
706
|
var emailLog = {
|
|
625
707
|
attrs: {
|
|
626
|
-
id:
|
|
708
|
+
id: id4(),
|
|
627
709
|
groupId: attr5("string", { indexed: true }),
|
|
628
710
|
applicationId: attr5("string", { indexed: true, optional: true }),
|
|
629
711
|
to: attr5("string", { indexed: true }),
|
|
@@ -638,7 +720,7 @@ var emailLog = {
|
|
|
638
720
|
sentAt: attr5("number", { indexed: true })
|
|
639
721
|
}
|
|
640
722
|
};
|
|
641
|
-
function chapterDb(mode, auth, includeNetworkNotes = false, application = resolveApplication(void 0), includeSignupControl = false, includeMemberContent = false, includeBuilderLibrary = false, includeLeaderAdmissions = false) {
|
|
723
|
+
function chapterDb(mode, auth, includeNetworkNotes = false, application = resolveApplication(void 0), includeSignupControl = false, includeMemberContent = false, includeBuilderLibrary = false, includeLeaderAdmissions = false, includeNetworkPersonRegistry = false) {
|
|
642
724
|
const entities = {};
|
|
643
725
|
if (mode === "chapter") {
|
|
644
726
|
entities.applications = applicationsFor(application);
|
|
@@ -672,6 +754,9 @@ function chapterDb(mode, auth, includeNetworkNotes = false, application = resolv
|
|
|
672
754
|
entities.leaderAdmissionDeliveries = leaderAdmissionDeliveriesEntity;
|
|
673
755
|
entities.leaderAdmissionMutations = leaderAdmissionMutationsEntity;
|
|
674
756
|
}
|
|
757
|
+
if (includeNetworkPersonRegistry) {
|
|
758
|
+
Object.assign(entities, networkPersonEntities);
|
|
759
|
+
}
|
|
675
760
|
const schema = { entities, links: {} };
|
|
676
761
|
const rules = {};
|
|
677
762
|
for (const ns of Object.keys(entities)) {
|
|
@@ -1323,9 +1408,9 @@ var APPLICATION_LABELS = {
|
|
|
1323
1408
|
phone: "Phone",
|
|
1324
1409
|
state: "State"
|
|
1325
1410
|
};
|
|
1326
|
-
function humanize(
|
|
1327
|
-
const text4 =
|
|
1328
|
-
return text4 ? `${text4[0].toUpperCase()}${text4.slice(1)}` :
|
|
1411
|
+
function humanize(id5) {
|
|
1412
|
+
const text4 = id5.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim();
|
|
1413
|
+
return text4 ? `${text4[0].toUpperCase()}${text4.slice(1)}` : id5;
|
|
1329
1414
|
}
|
|
1330
1415
|
function applicationDefs(chapter) {
|
|
1331
1416
|
try {
|
|
@@ -1334,23 +1419,23 @@ function applicationDefs(chapter) {
|
|
|
1334
1419
|
return {};
|
|
1335
1420
|
}
|
|
1336
1421
|
}
|
|
1337
|
-
function applicationType(
|
|
1422
|
+
function applicationType(id5, def) {
|
|
1338
1423
|
if (def && ["string", "email", "url", "enum"].includes(def.type)) return def.type;
|
|
1339
|
-
return
|
|
1424
|
+
return id5 === "email" ? "email" : id5 === "linkedin" ? "url" : "string";
|
|
1340
1425
|
}
|
|
1341
1426
|
function applicationFlowFields(chapter, application = chapter.application) {
|
|
1342
1427
|
const defs = applicationDefs(chapter);
|
|
1343
|
-
return [...application.required, ...application.optional].map((
|
|
1344
|
-
const def = defs[
|
|
1345
|
-
const conditions = application.conditions[
|
|
1346
|
-
const type = applicationType(
|
|
1428
|
+
return [...application.required, ...application.optional].map((id5, order) => {
|
|
1429
|
+
const def = defs[id5];
|
|
1430
|
+
const conditions = application.conditions[id5];
|
|
1431
|
+
const type = applicationType(id5, def);
|
|
1347
1432
|
return {
|
|
1348
|
-
id:
|
|
1349
|
-
label: def?.label ?? APPLICATION_LABELS[
|
|
1433
|
+
id: id5,
|
|
1434
|
+
label: def?.label ?? APPLICATION_LABELS[id5] ?? humanize(id5),
|
|
1350
1435
|
type,
|
|
1351
|
-
required: application.required.includes(
|
|
1436
|
+
required: application.required.includes(id5),
|
|
1352
1437
|
order,
|
|
1353
|
-
maxLength: application.maxLen[
|
|
1438
|
+
maxLength: application.maxLen[id5] ?? application.defaultMaxLen,
|
|
1354
1439
|
...type === "enum" && def?.options ? { options: [...def.options] } : {},
|
|
1355
1440
|
...conditions ? { conditions: { ...conditions } } : {},
|
|
1356
1441
|
...type === "email" ? { emailIdentity: "literal" } : {}
|
|
@@ -1360,17 +1445,17 @@ function applicationFlowFields(chapter, application = chapter.application) {
|
|
|
1360
1445
|
function resolveFormationFlowFields(crm, formation) {
|
|
1361
1446
|
if (!formation.enabled) return [];
|
|
1362
1447
|
const def = crm.type(formation.type);
|
|
1363
|
-
return [...formation.required, ...formation.optional].map((
|
|
1364
|
-
const field = def.fields[
|
|
1448
|
+
return [...formation.required, ...formation.optional].map((id5, order) => {
|
|
1449
|
+
const field = def.fields[id5];
|
|
1365
1450
|
return {
|
|
1366
|
-
id:
|
|
1367
|
-
label: field.label ?? humanize(
|
|
1451
|
+
id: id5,
|
|
1452
|
+
label: field.label ?? humanize(id5),
|
|
1368
1453
|
type: field.type,
|
|
1369
|
-
required: formation.required.includes(
|
|
1454
|
+
required: formation.required.includes(id5),
|
|
1370
1455
|
order,
|
|
1371
|
-
maxLength: formation.maxLen[
|
|
1456
|
+
maxLength: formation.maxLen[id5] ?? formation.defaultMaxLen,
|
|
1372
1457
|
...field.options ? { options: [...field.options] } : {},
|
|
1373
|
-
...
|
|
1458
|
+
...id5 === def.emailField || field.type === "email" ? { emailIdentity: "literal" } : {}
|
|
1374
1459
|
};
|
|
1375
1460
|
});
|
|
1376
1461
|
}
|
|
@@ -1664,12 +1749,30 @@ function resolveNetwork(config, crm) {
|
|
|
1664
1749
|
return { targets, readers };
|
|
1665
1750
|
}
|
|
1666
1751
|
|
|
1752
|
+
// src/config-network-person.ts
|
|
1753
|
+
var SLUG2 = /^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/;
|
|
1754
|
+
function resolveNetworkPersonRegistry(mode, input, targetIds) {
|
|
1755
|
+
if (!input) return null;
|
|
1756
|
+
if (mode !== "hub") throw new Error("defineChapter.networkPersonRegistry: only hub mode may own network Person authority");
|
|
1757
|
+
if (input.mode !== "shadow") throw new Error('defineChapter.networkPersonRegistry.mode: must be "shadow"');
|
|
1758
|
+
const chapterIds = input.chapterIds ? [...input.chapterIds] : [...targetIds];
|
|
1759
|
+
if (chapterIds.length === 0) throw new Error("defineChapter.networkPersonRegistry.chapterIds: at least one chapter is required");
|
|
1760
|
+
if (new Set(chapterIds).size !== chapterIds.length || chapterIds.some((id5) => !SLUG2.test(id5))) {
|
|
1761
|
+
throw new Error("defineChapter.networkPersonRegistry.chapterIds: expected distinct lowercase slugs");
|
|
1762
|
+
}
|
|
1763
|
+
const unknown = chapterIds.filter((id5) => !targetIds.includes(id5));
|
|
1764
|
+
if (unknown.length) {
|
|
1765
|
+
throw new Error(`defineChapter.networkPersonRegistry.chapterIds: ${unknown.map((id5) => `"${id5}"`).join(", ")} are not configured network targets`);
|
|
1766
|
+
}
|
|
1767
|
+
return { mode: "shadow", chapterIds };
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1667
1770
|
// src/config-signup-control.ts
|
|
1668
|
-
var
|
|
1771
|
+
var SLUG3 = /^[a-z0-9][a-z0-9-]{1,62}$/;
|
|
1669
1772
|
var SECRET_NAME = /^[a-z][a-z0-9_]{1,127}$/;
|
|
1670
1773
|
function resolveSignupControl(input) {
|
|
1671
1774
|
if (!input) return null;
|
|
1672
|
-
if (!
|
|
1775
|
+
if (!SLUG3.test(input.sourceId)) {
|
|
1673
1776
|
throw new Error("defineChapter.signupControl.sourceId: must be a lowercase app slug");
|
|
1674
1777
|
}
|
|
1675
1778
|
if (input.stripeMode !== "test" && input.stripeMode !== "live") {
|
|
@@ -1683,12 +1786,12 @@ function resolveSignupControl(input) {
|
|
|
1683
1786
|
}
|
|
1684
1787
|
|
|
1685
1788
|
// src/config-member-content.ts
|
|
1686
|
-
var
|
|
1789
|
+
var SLUG4 = /^[a-z0-9][a-z0-9-]{1,62}$/;
|
|
1687
1790
|
var SECRET_NAME2 = /^[a-z][a-z0-9_]{1,127}$/;
|
|
1688
1791
|
function resolveMemberContent(input) {
|
|
1689
1792
|
if (!input) return null;
|
|
1690
1793
|
const parent = input.parent;
|
|
1691
|
-
if (parent && !
|
|
1794
|
+
if (parent && !SLUG4.test(parent.sourceId)) {
|
|
1692
1795
|
throw new Error("defineChapter.memberContent.parent.sourceId: must be a lowercase app slug");
|
|
1693
1796
|
}
|
|
1694
1797
|
const secretName = parent?.secretName?.trim() || "member_content_control_secret";
|
|
@@ -1703,7 +1806,7 @@ function resolveMemberContent(input) {
|
|
|
1703
1806
|
}
|
|
1704
1807
|
|
|
1705
1808
|
// src/config-builder-library.ts
|
|
1706
|
-
var
|
|
1809
|
+
var SLUG5 = /^[a-z0-9][a-z0-9-]{1,62}$/;
|
|
1707
1810
|
function resolveBuilderLibrary(mode, input, network = { targets: [], readers: [] }) {
|
|
1708
1811
|
if (!input) return null;
|
|
1709
1812
|
if (input.sources !== void 0 && !Array.isArray(input.sources)) {
|
|
@@ -1711,7 +1814,7 @@ function resolveBuilderLibrary(mode, input, network = { targets: [], readers: []
|
|
|
1711
1814
|
}
|
|
1712
1815
|
const seen = /* @__PURE__ */ new Set();
|
|
1713
1816
|
const sources = (input.sources ?? []).map((source, index) => {
|
|
1714
|
-
if (!source || typeof source !== "object" || !
|
|
1817
|
+
if (!source || typeof source !== "object" || !SLUG5.test(source.sourceId)) {
|
|
1715
1818
|
throw new Error(`defineChapter.builderLibrary.sources[${index}].sourceId: must be a lowercase app slug`);
|
|
1716
1819
|
}
|
|
1717
1820
|
if (source.sourceId === "built-not-found" && mode === "hub") {
|
|
@@ -1742,15 +1845,15 @@ function resolveBuilderLibrary(mode, input, network = { targets: [], readers: []
|
|
|
1742
1845
|
}
|
|
1743
1846
|
|
|
1744
1847
|
// src/config.ts
|
|
1745
|
-
var
|
|
1848
|
+
var SLUG6 = /^[a-z0-9][a-z0-9-]{1,62}$/;
|
|
1746
1849
|
function isResolvedCrm(x) {
|
|
1747
1850
|
return !!x && typeof x === "object" && "prepare" in x && typeof x.prepare === "function";
|
|
1748
1851
|
}
|
|
1749
1852
|
function defineChapter(config) {
|
|
1750
1853
|
if (!config || typeof config !== "object") throw new Error("defineChapter: a config object is required");
|
|
1751
|
-
const { id:
|
|
1752
|
-
if (typeof
|
|
1753
|
-
throw new Error(`defineChapter.id: must be a lowercase slug [a-z0-9-] (2-63 chars) \u2014 got ${JSON.stringify(
|
|
1854
|
+
const { id: id5, name } = config;
|
|
1855
|
+
if (typeof id5 !== "string" || !SLUG6.test(id5)) {
|
|
1856
|
+
throw new Error(`defineChapter.id: must be a lowercase slug [a-z0-9-] (2-63 chars) \u2014 got ${JSON.stringify(id5)}`);
|
|
1754
1857
|
}
|
|
1755
1858
|
if (typeof name !== "string" || name.trim() === "") throw new Error("defineChapter.name: a non-empty name is required");
|
|
1756
1859
|
const mode = config.mode ?? "chapter";
|
|
@@ -1773,6 +1876,11 @@ function defineChapter(config) {
|
|
|
1773
1876
|
const brand = { ...config.brand, wordmark: config.brand?.wordmark ?? name };
|
|
1774
1877
|
const copy = resolveChapterCopy(config.copy);
|
|
1775
1878
|
const network = resolveNetwork(config, crm);
|
|
1879
|
+
const networkPersonRegistry = resolveNetworkPersonRegistry(
|
|
1880
|
+
mode,
|
|
1881
|
+
config.networkPersonRegistry,
|
|
1882
|
+
network.targets.map((target) => target.id)
|
|
1883
|
+
);
|
|
1776
1884
|
const signupControl = resolveSignupControl(config.signupControl);
|
|
1777
1885
|
const memberContent = resolveMemberContent(config.memberContent);
|
|
1778
1886
|
const builderLibrary = resolveBuilderLibrary(mode, config.builderLibrary, network);
|
|
@@ -1791,7 +1899,8 @@ function defineChapter(config) {
|
|
|
1791
1899
|
Boolean(signupControl),
|
|
1792
1900
|
Boolean(memberContent),
|
|
1793
1901
|
Boolean(builderLibrary),
|
|
1794
|
-
network.targets.some((target) => target.admissionGrants)
|
|
1902
|
+
network.targets.some((target) => target.admissionGrants),
|
|
1903
|
+
Boolean(networkPersonRegistry)
|
|
1795
1904
|
);
|
|
1796
1905
|
const services = config.services ?? ["db", "calendar", "o11y"];
|
|
1797
1906
|
const account = config.account ?? "none";
|
|
@@ -1841,7 +1950,7 @@ function defineChapter(config) {
|
|
|
1841
1950
|
};
|
|
1842
1951
|
const chapter = {
|
|
1843
1952
|
config,
|
|
1844
|
-
id:
|
|
1953
|
+
id: id5,
|
|
1845
1954
|
name,
|
|
1846
1955
|
mode,
|
|
1847
1956
|
brand,
|
|
@@ -1850,6 +1959,7 @@ function defineChapter(config) {
|
|
|
1850
1959
|
signupControl,
|
|
1851
1960
|
memberContent,
|
|
1852
1961
|
builderLibrary,
|
|
1962
|
+
networkPersonRegistry,
|
|
1853
1963
|
formation,
|
|
1854
1964
|
crm,
|
|
1855
1965
|
auth,
|
|
@@ -2161,7 +2271,8 @@ function createChapterIntegration(chapter, options = {}) {
|
|
|
2161
2271
|
{ path: "/api/builder-library-control", expectedStatus: 401 },
|
|
2162
2272
|
{ path: "/api/admin/builder-library", expectedStatus: 401 },
|
|
2163
2273
|
{ path: "/api/admin/builder-library/manifest", expectedStatus: 401 }
|
|
2164
|
-
] : []
|
|
2274
|
+
] : [],
|
|
2275
|
+
...chapter.networkPersonRegistry ? [{ path: "/api/admin/network-person-registry", expectedStatus: 401 }] : []
|
|
2165
2276
|
],
|
|
2166
2277
|
runbooks
|
|
2167
2278
|
};
|
|
@@ -2169,7 +2280,7 @@ function createChapterIntegration(chapter, options = {}) {
|
|
|
2169
2280
|
|
|
2170
2281
|
// src/member-content-validation-helpers.ts
|
|
2171
2282
|
var ID = /^[a-z][a-z0-9-]{0,79}$/;
|
|
2172
|
-
var
|
|
2283
|
+
var SLUG7 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
2173
2284
|
var ROOT_KEYS = /* @__PURE__ */ new Set(["schemaVersion", "revision", "generatedAt", "source", "target", "pages", "upsellOverrides"]);
|
|
2174
2285
|
var SOURCE_KEYS = /* @__PURE__ */ new Set(["type", "appId"]);
|
|
2175
2286
|
var TARGET_KEYS = /* @__PURE__ */ new Set(["chapterId", "environment"]);
|
|
@@ -2275,14 +2386,14 @@ function validateMemberContentDocument(input, options = {}) {
|
|
|
2275
2386
|
continue;
|
|
2276
2387
|
}
|
|
2277
2388
|
unknownKeys(raw, PAGE_KEYS, path, errors);
|
|
2278
|
-
const
|
|
2389
|
+
const id5 = textValue(raw.id, `${path}.id`, errors, 80, true) ?? "";
|
|
2279
2390
|
const slug = textValue(raw.slug, `${path}.slug`, errors, 120, true) ?? "";
|
|
2280
2391
|
const title = textValue(raw.title, `${path}.title`, errors, MAX_TEXT, true) ?? "";
|
|
2281
|
-
if (
|
|
2282
|
-
if (slug && !
|
|
2283
|
-
if (ids.has(
|
|
2392
|
+
if (id5 && !ID.test(id5)) errors.push(`${path}.id must be a lowercase kebab-case id`);
|
|
2393
|
+
if (slug && !SLUG7.test(slug)) errors.push(`${path}.slug must be a lowercase URL slug`);
|
|
2394
|
+
if (ids.has(id5) || knownParentIds.has(id5)) errors.push(`${path}.id duplicates page "${id5}"`);
|
|
2284
2395
|
if (slugs.has(slug) || (options.parentPages ?? []).some((page) => page.slug === slug)) errors.push(`${path}.slug duplicates "${slug}"`);
|
|
2285
|
-
ids.add(
|
|
2396
|
+
ids.add(id5);
|
|
2286
2397
|
slugs.add(slug);
|
|
2287
2398
|
const navRaw = record(raw.navigation);
|
|
2288
2399
|
let navigation = { section: "General", order: index };
|
|
@@ -2338,7 +2449,7 @@ function validateMemberContentDocument(input, options = {}) {
|
|
|
2338
2449
|
else if (owner === "chapter") upsell = { owner, ...offer ? { offer } : {} };
|
|
2339
2450
|
}
|
|
2340
2451
|
}
|
|
2341
|
-
pages.push({ id:
|
|
2452
|
+
pages.push({ id: id5, slug, title, ...summary ? { summary } : {}, navigation, audience, ...teaserMarkdown ? { teaserMarkdown } : {}, bodyMarkdown, ...upsell ? { upsell } : {} });
|
|
2342
2453
|
}
|
|
2343
2454
|
const allIds = /* @__PURE__ */ new Set([...knownParentIds, ...ids]);
|
|
2344
2455
|
for (const [index, page] of pages.entries()) {
|
|
@@ -2544,8 +2655,8 @@ function resourceValue(value, path, errors) {
|
|
|
2544
2655
|
return null;
|
|
2545
2656
|
}
|
|
2546
2657
|
unknownKeys2(raw, RESOURCE_KEYS, path, errors);
|
|
2547
|
-
const
|
|
2548
|
-
if (
|
|
2658
|
+
const id5 = text(raw.id, `${path}.id`, errors, 80) ?? "";
|
|
2659
|
+
if (id5 && !ID2.test(id5)) errors.push(`${path}.id must be lowercase kebab-case`);
|
|
2549
2660
|
const kind = text(raw.kind, `${path}.kind`, errors) ?? "";
|
|
2550
2661
|
if (!KINDS.has(kind)) errors.push(`${path}.kind is unsupported`);
|
|
2551
2662
|
const title = text(raw.title, `${path}.title`, errors, 240) ?? "";
|
|
@@ -2602,7 +2713,7 @@ function resourceValue(value, path, errors) {
|
|
|
2602
2713
|
updatedAt: integer(provenanceRaw?.updatedAt, `${path}.provenance.updatedAt`, errors, 0),
|
|
2603
2714
|
...promotedFrom ? { promotedFrom } : {}
|
|
2604
2715
|
};
|
|
2605
|
-
return { id:
|
|
2716
|
+
return { id: id5, kind, title, ...summary ? { summary } : {}, tags, scope, status, revision, ...bodyMarkdown ? { bodyMarkdown } : {}, ...url ? { url } : {}, ...brandAsset ? { brandAsset } : {}, provenance };
|
|
2606
2717
|
}
|
|
2607
2718
|
function validateBuilderLibraryDocument(value, options = {}) {
|
|
2608
2719
|
const errors = [];
|
|
@@ -2633,7 +2744,7 @@ function validateBuilderLibraryDocument(value, options = {}) {
|
|
|
2633
2744
|
const inputs = Array.isArray(raw.resources) ? raw.resources : [];
|
|
2634
2745
|
if (inputs.length > MAX_RESOURCES) errors.push(`document.resources may contain at most ${MAX_RESOURCES} items`);
|
|
2635
2746
|
const resources = inputs.map((item, index) => resourceValue(item, `document.resources[${index}]`, errors)).filter(Boolean);
|
|
2636
|
-
const ids = resources.map(({ id:
|
|
2747
|
+
const ids = resources.map(({ id: id5 }) => id5);
|
|
2637
2748
|
if (new Set(ids).size !== ids.length) errors.push("document.resources ids must be unique");
|
|
2638
2749
|
for (const resource of resources) {
|
|
2639
2750
|
if (sourceType === "chapter" && (resource.scope.kind !== "chapter" || resource.scope.chapterId !== sourceAppId)) {
|
|
@@ -2788,9 +2899,9 @@ async function sendTemplated(deps, input) {
|
|
|
2788
2899
|
error = e instanceof Error ? e.message : String(e);
|
|
2789
2900
|
}
|
|
2790
2901
|
}
|
|
2791
|
-
const
|
|
2902
|
+
const id5 = deps.newId();
|
|
2792
2903
|
const row = {
|
|
2793
|
-
id:
|
|
2904
|
+
id: id5,
|
|
2794
2905
|
groupId: input.group.id,
|
|
2795
2906
|
to: decision.to,
|
|
2796
2907
|
template: input.template,
|
|
@@ -2804,7 +2915,7 @@ async function sendTemplated(deps, input) {
|
|
|
2804
2915
|
...messageId ? { messageId } : {},
|
|
2805
2916
|
...error ? { error } : {}
|
|
2806
2917
|
};
|
|
2807
|
-
await deps.db.transact([{ t: "update", ns: "emailLog", id:
|
|
2918
|
+
await deps.db.transact([{ t: "update", ns: "emailLog", id: id5, attrs: row }], error ? void 0 : { mutationId: `email:${input.dedupeKey}` });
|
|
2808
2919
|
return error ? { sent: false, reason: error } : { sent: true };
|
|
2809
2920
|
}
|
|
2810
2921
|
function emailGroupFrom(row) {
|
|
@@ -2992,14 +3103,14 @@ function validateAdmissionGrantDocument(input) {
|
|
|
2992
3103
|
const seenEmails = /* @__PURE__ */ new Set();
|
|
2993
3104
|
for (const [index, raw] of rawGrants.slice(0, MAX_GRANTS).entries()) {
|
|
2994
3105
|
const grant = raw && typeof raw === "object" ? raw : {};
|
|
2995
|
-
const
|
|
3106
|
+
const id5 = typeof grant.id === "string" ? grant.id : "";
|
|
2996
3107
|
const email = typeof grant.email === "string" ? grant.email.trim() : "";
|
|
2997
3108
|
const normalized = normalizeAdmissionEmail(email);
|
|
2998
3109
|
const decision = grant.decision;
|
|
2999
3110
|
const note = typeof grant.note === "string" ? grant.note.trim() : void 0;
|
|
3000
3111
|
const expiresAt = grant.expiresAt === void 0 ? void 0 : Number(grant.expiresAt);
|
|
3001
|
-
if (!ID3.test(
|
|
3002
|
-
if (seenIds.has(
|
|
3112
|
+
if (!ID3.test(id5)) errors.push(`document.grants[${index}].id must be an identifier`);
|
|
3113
|
+
if (seenIds.has(id5)) errors.push(`document.grants repeats id "${id5}"`);
|
|
3003
3114
|
if (!isAdmissionEmail(normalized)) errors.push(`document.grants[${index}].email must be valid`);
|
|
3004
3115
|
if (seenEmails.has(normalized)) errors.push(`document.grants repeats email "${normalized}"`);
|
|
3005
3116
|
if (decision !== "waive_interview" && decision !== "require_interview") {
|
|
@@ -3009,10 +3120,10 @@ function validateAdmissionGrantDocument(input) {
|
|
|
3009
3120
|
if (expiresAt !== void 0 && (!Number.isFinite(expiresAt) || expiresAt <= 0)) {
|
|
3010
3121
|
errors.push(`document.grants[${index}].expiresAt must be epoch milliseconds`);
|
|
3011
3122
|
}
|
|
3012
|
-
seenIds.add(
|
|
3123
|
+
seenIds.add(id5);
|
|
3013
3124
|
seenEmails.add(normalized);
|
|
3014
3125
|
grants.push({
|
|
3015
|
-
id:
|
|
3126
|
+
id: id5,
|
|
3016
3127
|
email,
|
|
3017
3128
|
decision,
|
|
3018
3129
|
...note ? { note } : {},
|
|
@@ -3083,8 +3194,8 @@ async function materializeAdmissionGrants(db, envelope, previous, receivedAt) {
|
|
|
3083
3194
|
const incomingIds = new Set(document.grants.map((grant) => `admission:parent:${document.source.appId}:${grant.id}`));
|
|
3084
3195
|
const ops = [];
|
|
3085
3196
|
for (const row of current) {
|
|
3086
|
-
const
|
|
3087
|
-
if (
|
|
3197
|
+
const id5 = String(row.id ?? "");
|
|
3198
|
+
if (id5 && !incomingIds.has(id5)) ops.push({ t: "update", ns: "admissionGrants", id: id5, attrs: {
|
|
3088
3199
|
active: false,
|
|
3089
3200
|
revokedAt: receivedAt,
|
|
3090
3201
|
revokedBy: document.source.actor,
|
|
@@ -3093,10 +3204,10 @@ async function materializeAdmissionGrants(db, envelope, previous, receivedAt) {
|
|
|
3093
3204
|
} });
|
|
3094
3205
|
}
|
|
3095
3206
|
for (const grant of document.grants) {
|
|
3096
|
-
const
|
|
3097
|
-
const existing = current.find((row) => row.id ===
|
|
3098
|
-
ops.push({ t: "update", ns: "admissionGrants", id:
|
|
3099
|
-
id:
|
|
3207
|
+
const id5 = `admission:parent:${document.source.appId}:${grant.id}`;
|
|
3208
|
+
const existing = current.find((row) => row.id === id5);
|
|
3209
|
+
ops.push({ t: "update", ns: "admissionGrants", id: id5, attrs: {
|
|
3210
|
+
id: id5,
|
|
3100
3211
|
sourceGrantId: grant.id,
|
|
3101
3212
|
sourceScope: "parent",
|
|
3102
3213
|
sourceId: document.source.appId,
|
|
@@ -3117,7 +3228,7 @@ async function materializeAdmissionGrants(db, envelope, previous, receivedAt) {
|
|
|
3117
3228
|
...!grant.note && existing?.note !== void 0 ? ["note"] : [],
|
|
3118
3229
|
...grant.expiresAt === void 0 && existing?.expiresAt !== void 0 ? ["expiresAt"] : []
|
|
3119
3230
|
];
|
|
3120
|
-
if (retract.length) ops.push({ t: "retract", ns: "admissionGrants", id:
|
|
3231
|
+
if (retract.length) ops.push({ t: "retract", ns: "admissionGrants", id: id5, attrs: retract });
|
|
3121
3232
|
}
|
|
3122
3233
|
if (previous?.active) ops.push({ t: "update", ns: "admissionGrantRevisions", id: previous.id, attrs: { active: false } });
|
|
3123
3234
|
const revisionId = `admission-revision:${document.source.appId}:${document.target.environment}:${document.revision}`;
|
|
@@ -3187,10 +3298,10 @@ function validateGiftOfferCatalog(input, tierIds) {
|
|
|
3187
3298
|
}
|
|
3188
3299
|
const allowed2 = /* @__PURE__ */ new Set(["id", "target", "billingMode", "stripePriceId", "priceCents", "currency", "redemptionLifetimeHours", "activeFrom", "activeUntil", "title", "description", "ctaLabel"]);
|
|
3189
3300
|
for (const key of Object.keys(item)) if (!allowed2.has(key)) errors.push(`${path}.${key} is not supported`);
|
|
3190
|
-
const
|
|
3191
|
-
if (
|
|
3192
|
-
if (ids.has(
|
|
3193
|
-
ids.add(
|
|
3301
|
+
const id5 = text2(item.id, `${path}.id`, errors, 80);
|
|
3302
|
+
if (id5 && !ID4.test(id5)) errors.push(`${path}.id must be a lowercase kebab-case id`);
|
|
3303
|
+
if (ids.has(id5)) errors.push(`${path}.id duplicates "${id5}"`);
|
|
3304
|
+
ids.add(id5);
|
|
3194
3305
|
const targetRaw = record3(item.target);
|
|
3195
3306
|
let target = { type: "entitlement", entitlementKey: "invalid" };
|
|
3196
3307
|
if (targetRaw?.type === "tier") {
|
|
@@ -3216,7 +3327,7 @@ function validateGiftOfferCatalog(input, tierIds) {
|
|
|
3216
3327
|
if (activeUntil !== void 0 && (!Number.isSafeInteger(activeUntil) || activeUntil < 1)) errors.push(`${path}.activeUntil must be epoch milliseconds`);
|
|
3217
3328
|
if (activeFrom !== void 0 && activeUntil !== void 0 && activeUntil <= activeFrom) errors.push(`${path}.activeUntil must follow activeFrom`);
|
|
3218
3329
|
offers.push({
|
|
3219
|
-
id:
|
|
3330
|
+
id: id5,
|
|
3220
3331
|
target,
|
|
3221
3332
|
billingMode: item.billingMode,
|
|
3222
3333
|
stripePriceId,
|
|
@@ -3634,9 +3745,9 @@ async function updateClerkUserMetadataByEmail(secretKey, email, input, fetchImpl
|
|
|
3634
3745
|
const found = await fetchImpl(`https://api.clerk.com/v1/users?email_address=${encodeURIComponent(email)}&limit=1`, { headers: auth });
|
|
3635
3746
|
if (!found.ok) return false;
|
|
3636
3747
|
const users = await found.json().catch(() => null);
|
|
3637
|
-
const
|
|
3638
|
-
if (!
|
|
3639
|
-
return updateClerkUserMetadata(secretKey,
|
|
3748
|
+
const id5 = Array.isArray(users) && typeof users[0]?.id === "string" ? users[0].id : void 0;
|
|
3749
|
+
if (!id5) return false;
|
|
3750
|
+
return updateClerkUserMetadata(secretKey, id5, input, fetchImpl);
|
|
3640
3751
|
}
|
|
3641
3752
|
async function createClerkUser(secretKey, input, fetchImpl = fetch) {
|
|
3642
3753
|
const { path, body } = clerkUserRequest(input);
|
|
@@ -3699,8 +3810,8 @@ async function clerkGetUserByEmail(secretKey, email, fetchImpl = fetch) {
|
|
|
3699
3810
|
const user = Array.isArray(data) ? data[0] : void 0;
|
|
3700
3811
|
return user ? toRecord(user) : null;
|
|
3701
3812
|
}
|
|
3702
|
-
async function clerkGetUser(secretKey,
|
|
3703
|
-
const data = await clerkGet(`/v1/users/${encodeURIComponent(
|
|
3813
|
+
async function clerkGetUser(secretKey, id5, fetchImpl = fetch) {
|
|
3814
|
+
const data = await clerkGet(`/v1/users/${encodeURIComponent(id5)}`, secretKey, fetchImpl).catch(() => null);
|
|
3704
3815
|
return data ? toRecord(data) : null;
|
|
3705
3816
|
}
|
|
3706
3817
|
async function clerkListUsers(secretKey, fetchImpl = fetch) {
|
|
@@ -3716,8 +3827,8 @@ async function clerkListUsers(secretKey, fetchImpl = fetch) {
|
|
|
3716
3827
|
}
|
|
3717
3828
|
return out;
|
|
3718
3829
|
}
|
|
3719
|
-
async function clerkSetRole(secretKey,
|
|
3720
|
-
const res = await fetchImpl(`${CLERK_API}/v1/users/${encodeURIComponent(
|
|
3830
|
+
async function clerkSetRole(secretKey, id5, role, fetchImpl = fetch) {
|
|
3831
|
+
const res = await fetchImpl(`${CLERK_API}/v1/users/${encodeURIComponent(id5)}/metadata`, {
|
|
3721
3832
|
method: "PATCH",
|
|
3722
3833
|
headers: { authorization: `Bearer ${secretKey}`, "content-type": "application/json" },
|
|
3723
3834
|
body: JSON.stringify({ public_metadata: { role } })
|
|
@@ -4283,7 +4394,7 @@ function membershipPageDocument(input, options = {}) {
|
|
|
4283
4394
|
}
|
|
4284
4395
|
|
|
4285
4396
|
// src/signup-control-validate.ts
|
|
4286
|
-
var
|
|
4397
|
+
var SLUG8 = /^[a-z0-9][a-z0-9-]{1,62}$/;
|
|
4287
4398
|
var ENVIRONMENT = /^[a-z][a-z0-9_-]{0,62}$/;
|
|
4288
4399
|
var TIER = /^[a-z][a-z0-9-]{0,79}$/;
|
|
4289
4400
|
var PRICE2 = /^price_[A-Za-z0-9]{12,}$/;
|
|
@@ -4329,10 +4440,10 @@ function tiersOf(value, errors) {
|
|
|
4329
4440
|
return [];
|
|
4330
4441
|
}
|
|
4331
4442
|
unknownKeys3(item, TIER_KEYS2, path, errors);
|
|
4332
|
-
const
|
|
4333
|
-
if (
|
|
4334
|
-
if (seen.has(
|
|
4335
|
-
seen.add(
|
|
4443
|
+
const id5 = text3(item.id, `${path}.id`, errors, 80);
|
|
4444
|
+
if (id5 && !TIER.test(id5)) errors.push(`${path}.id must be a lowercase kebab-case id`);
|
|
4445
|
+
if (seen.has(id5)) errors.push(`${path}.id duplicates "${id5}"`);
|
|
4446
|
+
seen.add(id5);
|
|
4336
4447
|
const name = text3(item.name, `${path}.name`, errors, 160);
|
|
4337
4448
|
if (typeof item.available !== "boolean") errors.push(`${path}.available must be boolean`);
|
|
4338
4449
|
if (!Number.isInteger(item.sortOrder) || Number(item.sortOrder) < 0) errors.push(`${path}.sortOrder must be a non-negative integer`);
|
|
@@ -4347,7 +4458,7 @@ function tiersOf(value, errors) {
|
|
|
4347
4458
|
}
|
|
4348
4459
|
const blurb = item.blurb === void 0 ? void 0 : text3(item.blurb, `${path}.blurb`, errors, 4e3);
|
|
4349
4460
|
return [{
|
|
4350
|
-
id:
|
|
4461
|
+
id: id5,
|
|
4351
4462
|
name,
|
|
4352
4463
|
available: item.available === true,
|
|
4353
4464
|
sortOrder: Number(item.sortOrder) || 0,
|
|
@@ -4442,8 +4553,8 @@ function validateSignupControlDocument(input) {
|
|
|
4442
4553
|
const appId = text3(source?.appId, "document.source.appId", errors, 63);
|
|
4443
4554
|
const chapterId = text3(target?.chapterId, "document.target.chapterId", errors, 63);
|
|
4444
4555
|
const environment = text3(target?.environment, "document.target.environment", errors, 63);
|
|
4445
|
-
if (appId && !
|
|
4446
|
-
if (chapterId && !
|
|
4556
|
+
if (appId && !SLUG8.test(appId)) errors.push("document.source.appId must be a lowercase app slug");
|
|
4557
|
+
if (chapterId && !SLUG8.test(chapterId)) errors.push("document.target.chapterId must be a lowercase app slug");
|
|
4447
4558
|
if (environment && !ENVIRONMENT.test(environment)) errors.push("document.target.environment is invalid");
|
|
4448
4559
|
if (target?.stripeMode !== "test" && target?.stripeMode !== "live") errors.push("document.target.stripeMode must be test or live");
|
|
4449
4560
|
const tiers2 = tiersOf(root.tiers, errors);
|
|
@@ -4722,7 +4833,7 @@ var exclusions = (chapterId, paidTierIds) => [
|
|
|
4722
4833
|
id: chapterId,
|
|
4723
4834
|
reason: "provider_identity",
|
|
4724
4835
|
paths: [
|
|
4725
|
-
...paidTierIds.map((
|
|
4836
|
+
...paidTierIds.map((id5) => `tiers[${id5}].stripePriceId`),
|
|
4726
4837
|
"groups.stripePublishableKey",
|
|
4727
4838
|
"applications.stripeCustomerId",
|
|
4728
4839
|
"applications.stripeSubscriptionId",
|
|
@@ -4764,9 +4875,9 @@ async function exportChapterPromotion(input) {
|
|
|
4764
4875
|
sourceIds: [`signup-control:${document.revision}`, document.source.appId, document.target.chapterId].sort(),
|
|
4765
4876
|
receiptDigests: [input.digest]
|
|
4766
4877
|
};
|
|
4767
|
-
const artifact = (kind,
|
|
4878
|
+
const artifact = (kind, id5, content) => ({
|
|
4768
4879
|
kind,
|
|
4769
|
-
id:
|
|
4880
|
+
id: id5,
|
|
4770
4881
|
sourceRevision: revision,
|
|
4771
4882
|
provenance: promotionProvenance,
|
|
4772
4883
|
content: canonicalPromotionValue(content)
|
|
@@ -4805,7 +4916,7 @@ async function exportChapterPromotion(input) {
|
|
|
4805
4916
|
}
|
|
4806
4917
|
|
|
4807
4918
|
// src/member-system-authority.ts
|
|
4808
|
-
var rows2 = (group) => group.fields.map((
|
|
4919
|
+
var rows2 = (group) => group.fields.map((id5) => ({ ...group, id: id5 }));
|
|
4809
4920
|
var MEMBER_SYSTEM_AUTHORITY_MATRIX = [
|
|
4810
4921
|
...rows2({
|
|
4811
4922
|
scope: "network",
|
|
@@ -5394,6 +5505,7 @@ export {
|
|
|
5394
5505
|
resolveJoinContinuation,
|
|
5395
5506
|
resolveLeaderFormation,
|
|
5396
5507
|
resolveMemberContent,
|
|
5508
|
+
resolveNetworkPersonRegistry,
|
|
5397
5509
|
resolvePipeline,
|
|
5398
5510
|
resolveScheduling,
|
|
5399
5511
|
resolveSignupControl,
|