@odla-ai/chapter 0.14.0 → 0.15.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 +14 -7
- package/dist/index.cjs +14 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -151,11 +151,15 @@ These bite silently — a smoke test won't catch them:
|
|
|
151
151
|
**Re-check this on every chapter upgrade.** Wiring a send changes a site's
|
|
152
152
|
outbound mail with no local diff — release notes call out send changes
|
|
153
153
|
explicitly for that reason.
|
|
154
|
-
- **Account model
|
|
155
|
-
`"create"` makes the account server-side (so join can say the
|
|
156
|
-
ready), `"
|
|
157
|
-
|
|
158
|
-
|
|
154
|
+
- **Account model — the default is `"none"`, and that is deliberate.**
|
|
155
|
+
`account: "create"` makes the Clerk account server-side (so join can say the
|
|
156
|
+
account is ready), `"invite"` **emails the applicant a Clerk invitation**, and
|
|
157
|
+
`"none"` (the default) provisions nothing. Both non-default models need
|
|
158
|
+
`clerk_secret_key` in the tenant vault. The default is side-effect-free on
|
|
159
|
+
purpose: inviting mails a real person, and a site that never made that choice
|
|
160
|
+
must not be sending mail. **You must opt in — a site that wants accounts and
|
|
161
|
+
doesn't set `account` will silently provision none.** (Changed in 0.15.0: the
|
|
162
|
+
default was `"invite"`, which mailed applicants from a config nobody wrote.)
|
|
159
163
|
- **What lands on the Clerk account (and its `public_metadata` is
|
|
160
164
|
client-readable).** Both models write `public_metadata` as
|
|
161
165
|
`{ applicationId, profile }`. By default `profile` is every configured
|
|
@@ -176,8 +180,11 @@ These bite silently — a smoke test won't catch them:
|
|
|
176
180
|
A valid application is never newly rejected.
|
|
177
181
|
- **CRM enrichment.** `projectApplicant` writes the base identity/contact person.
|
|
178
182
|
To carry more of the application into the CRM, list `application: { crmFields:
|
|
179
|
-
[...] }
|
|
180
|
-
|
|
183
|
+
[...] }`. Each name is **cross-checked against your crm `person` type at
|
|
184
|
+
`defineChapter()` time and throws** if it isn't declared there — an undeclared
|
|
185
|
+
field would otherwise be dropped by the projection while the base person still
|
|
186
|
+
lands, making a typo invisible. (The runtime projection still falls back to the
|
|
187
|
+
base person if a write fails, so an applicant is never lost.) Stage mirroring,
|
|
181
188
|
billing snapshots and Clerk-identity linking stay yours as host routes.
|
|
182
189
|
- **Disclaimer acknowledgement.** A truthy `disclaimerAck` on the submit body
|
|
183
190
|
(boolean or the string a plain form posts) stamps `disclaimerAckAt` from the
|
package/dist/index.cjs
CHANGED
|
@@ -607,10 +607,23 @@ function defineChapter(config) {
|
|
|
607
607
|
const application = resolveApplication(config.application);
|
|
608
608
|
const { schema, rules } = chapterDb(mode, auth);
|
|
609
609
|
const services = config.services ?? ["db", "calendar", "o11y"];
|
|
610
|
-
const account = config.account ?? "
|
|
610
|
+
const account = config.account ?? "none";
|
|
611
611
|
if (account !== "invite" && account !== "create" && account !== "none") {
|
|
612
612
|
throw new Error(`defineChapter.account: must be "invite", "create", or "none" \u2014 got "${String(account)}"`);
|
|
613
613
|
}
|
|
614
|
+
if (application.crmFields.length > 0) {
|
|
615
|
+
let personFields = null;
|
|
616
|
+
try {
|
|
617
|
+
personFields = Object.keys(crm.type("person").fields ?? {});
|
|
618
|
+
} catch {
|
|
619
|
+
}
|
|
620
|
+
const unknown = personFields ? application.crmFields.filter((f) => !personFields.includes(f)) : [];
|
|
621
|
+
if (unknown.length > 0) {
|
|
622
|
+
throw new Error(
|
|
623
|
+
`defineChapter.application.crmFields: ${unknown.map((f) => `"${f}"`).join(", ")} not declared on the CRM "person" type (declared: ${personFields?.join(", ")}). An undeclared field is silently dropped from the CRM projection \u2014 add it to your crm config's person fields, or remove it from crmFields.`
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
614
627
|
const adminNotification = config.sends?.adminNotification ?? "submit";
|
|
615
628
|
if (adminNotification !== "submit" && adminNotification !== "payment" && adminNotification !== "never") {
|
|
616
629
|
throw new Error(
|