@odla-ai/chapter 0.10.1 → 0.11.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 +21 -3
- package/dist/index.cjs +12 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -2
- package/dist/index.d.ts +17 -2
- package/dist/index.js +12 -3
- package/dist/index.js.map +1 -1
- package/dist/worker/index.cjs +17 -3
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +7 -0
- package/dist/worker/index.d.ts +7 -0
- package/dist/worker/index.js +17 -3
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -175,6 +175,12 @@ interface ChapterApplication {
|
|
|
175
175
|
defaultMaxLen?: number;
|
|
176
176
|
/** Max JSON request body in bytes. Default 32768. */
|
|
177
177
|
bodyCap?: number;
|
|
178
|
+
/** Reject a submit that carries no truthy `disclaimerAck` (400), instead of
|
|
179
|
+
* writing a row with no consent record. Default `false` for back-compat —
|
|
180
|
+
* but turn it on if the disclaimer is a compliance record: a missing ack is
|
|
181
|
+
* otherwise silent, permanent and unreconstructible. Failure is deterministic
|
|
182
|
+
* and surfaces on the first test submit, not intermittently in production. */
|
|
183
|
+
requireDisclaimerAck?: boolean;
|
|
178
184
|
}
|
|
179
185
|
/** The fully-resolved application config carried on the {@link Chapter}. */
|
|
180
186
|
interface ResolvedApplication {
|
|
@@ -183,6 +189,7 @@ interface ResolvedApplication {
|
|
|
183
189
|
maxLen: Record<string, number>;
|
|
184
190
|
defaultMaxLen: number;
|
|
185
191
|
bodyCap: number;
|
|
192
|
+
requireDisclaimerAck: boolean;
|
|
186
193
|
}
|
|
187
194
|
/** The `defineChapter()` config a site fills in. */
|
|
188
195
|
interface ChapterConfig {
|
|
@@ -625,6 +632,9 @@ declare function canceledPatch(): {
|
|
|
625
632
|
|
|
626
633
|
/** Apply defaults + validate the application config. Throws at import on bad shape. */
|
|
627
634
|
declare function resolveApplication(a: ChapterApplication | undefined): ResolvedApplication;
|
|
635
|
+
/** Whether a submit body carries a genuine disclaimer acknowledgement. Accepts
|
|
636
|
+
* the boolean an API client sends and the string a plain HTML form posts. */
|
|
637
|
+
declare function hasDisclaimerAck(fields: Record<string, unknown>): boolean;
|
|
628
638
|
/**
|
|
629
639
|
* The applicant profile written to the Clerk account's `public_metadata.profile`:
|
|
630
640
|
* every configured application field Clerk does not already carry natively, plus
|
|
@@ -633,12 +643,17 @@ declare function resolveApplication(a: ChapterApplication | undefined): Resolved
|
|
|
633
643
|
* there is nothing to write.
|
|
634
644
|
*/
|
|
635
645
|
declare function applicantProfile(chapter: Chapter, fields: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
636
|
-
/** A validated submission, or a 400-worthy validation error the route returns.
|
|
646
|
+
/** A validated submission, or a 400-worthy validation error the route returns.
|
|
647
|
+
* `disclaimerAckAt` reports what THIS request recorded — a number when consent
|
|
648
|
+
* was stamped, `null` when none was supplied. It is always present so a missing
|
|
649
|
+
* consent record is visible in the response rather than silently absent from a
|
|
650
|
+
* row nobody reads until an audit. */
|
|
637
651
|
type SubmitResult = {
|
|
638
652
|
ok: true;
|
|
639
653
|
id: string;
|
|
640
654
|
duplicate: boolean;
|
|
641
655
|
status: string;
|
|
656
|
+
disclaimerAckAt: number | null;
|
|
642
657
|
} | {
|
|
643
658
|
ok: false;
|
|
644
659
|
error: string;
|
|
@@ -1016,4 +1031,4 @@ type ApplicationBookingPatch = {
|
|
|
1016
1031
|
* already there (never backward). */
|
|
1017
1032
|
declare function applicationBookingUpdate(currentStatus: string, startAt: number, htmlLink?: string | null): ApplicationBookingPatch;
|
|
1018
1033
|
|
|
1019
|
-
export { type AccountModel, type AdminNotificationTrigger, type Applicant, type ApplicationBookingPatch, type ApplicationRecord, type ApplicationSummary, type Attr, type AttrType, type Chapter, type ChapterApplication, type ChapterAuth, type ChapterBrand, type ChapterConfig, type ChapterDb, type ChapterEmails, type ChapterIntegrationDescriptor, type ChapterIntegrationOptions, type ChapterMode, type ChapterPipeline, type ChapterPolicy, type ChapterPrices, type ChapterScheduling, type ChapterSends, type ClerkInviteInput, type ClerkResult, type ClerkUserInput, type DbOp, type DbRules, type DbSchema, type DeliveryDecision, type EmailGroup, type EmailTemplate, type EmailTemplateRow, type Entity, type ExistingMeeting, type GuardResult, type JoinConfigGroup, type LiveEvent, type MailSender, type MeetingForReconcile, type MeetingRecord, type MeetingReschedulePatch, type MemberApplication, type MemberSession, type NewMeetingRow, type NotifyDeps, type NotifyInput, type NotifyResult, type PaymentsGroup, type ProjectionDeps, type ReconcileDecision, type ResolvedApplication, type ResolvedAuth, type ResolvedPipeline, type ResolvedScheduling, type ResolvedSends, type RoleChangeContext, type Rule, SCHEDULING_DEFAULTS, type SchedulingErrors, type SecretStore, type SessionUser, type SharedPerson, type StripeEvent, type SubmitResult, type WebhookEvent, applicantProfile, applicationBookingUpdate, applicationSummary, bookingDecision, brandTokens, buildGroupSeed, canApprove, canBook, canChangeRole, canTransition, canceledPatch, chapterDb, clerkInviteRequest, clerkUserRequest, createChapterIntegration, createClerkInvitation, createClerkUser, defaultCrm, defineChapter, emailGroupFrom, endForSlot, findApplicationRef, firstPaymentPatch, getVaultSecret, introIdempotencyKey, isAdminRole, isAlreadySent, isReconcilable, isSlotAvailable, joinConfig, meetingCreateRow, meetingRescheduleUpdate, memberApplication, memberSession, normalizeWebhookEvent, paymentsReady, planDelivery, projectApplicant, projectSharedRecord, reconcileMeetings, refundedPatch, render, renderSummary, renderTemplateBody, renewalPatch, resolveApplication, resolveAuth, resolvePipeline, resolveScheduling, roleFromClaim, sendTemplated, sharedPersonInput, slotWindow, stageIndex, stripeForm, submitApplication, subscriptionIdempotencyKey, validateScheduling, verifyStripeSignature, webhookMutationId };
|
|
1034
|
+
export { type AccountModel, type AdminNotificationTrigger, type Applicant, type ApplicationBookingPatch, type ApplicationRecord, type ApplicationSummary, type Attr, type AttrType, type Chapter, type ChapterApplication, type ChapterAuth, type ChapterBrand, type ChapterConfig, type ChapterDb, type ChapterEmails, type ChapterIntegrationDescriptor, type ChapterIntegrationOptions, type ChapterMode, type ChapterPipeline, type ChapterPolicy, type ChapterPrices, type ChapterScheduling, type ChapterSends, type ClerkInviteInput, type ClerkResult, type ClerkUserInput, type DbOp, type DbRules, type DbSchema, type DeliveryDecision, type EmailGroup, type EmailTemplate, type EmailTemplateRow, type Entity, type ExistingMeeting, type GuardResult, type JoinConfigGroup, type LiveEvent, type MailSender, type MeetingForReconcile, type MeetingRecord, type MeetingReschedulePatch, type MemberApplication, type MemberSession, type NewMeetingRow, type NotifyDeps, type NotifyInput, type NotifyResult, type PaymentsGroup, type ProjectionDeps, type ReconcileDecision, type ResolvedApplication, type ResolvedAuth, type ResolvedPipeline, type ResolvedScheduling, type ResolvedSends, type RoleChangeContext, type Rule, SCHEDULING_DEFAULTS, type SchedulingErrors, type SecretStore, type SessionUser, type SharedPerson, type StripeEvent, type SubmitResult, type WebhookEvent, applicantProfile, applicationBookingUpdate, applicationSummary, bookingDecision, brandTokens, buildGroupSeed, canApprove, canBook, canChangeRole, canTransition, canceledPatch, chapterDb, clerkInviteRequest, clerkUserRequest, createChapterIntegration, createClerkInvitation, createClerkUser, defaultCrm, defineChapter, emailGroupFrom, endForSlot, findApplicationRef, firstPaymentPatch, getVaultSecret, hasDisclaimerAck, introIdempotencyKey, isAdminRole, isAlreadySent, isReconcilable, isSlotAvailable, joinConfig, meetingCreateRow, meetingRescheduleUpdate, memberApplication, memberSession, normalizeWebhookEvent, paymentsReady, planDelivery, projectApplicant, projectSharedRecord, reconcileMeetings, refundedPatch, render, renderSummary, renderTemplateBody, renewalPatch, resolveApplication, resolveAuth, resolvePipeline, resolveScheduling, roleFromClaim, sendTemplated, sharedPersonInput, slotWindow, stageIndex, stripeForm, submitApplication, subscriptionIdempotencyKey, validateScheduling, verifyStripeSignature, webhookMutationId };
|
package/dist/index.d.ts
CHANGED
|
@@ -175,6 +175,12 @@ interface ChapterApplication {
|
|
|
175
175
|
defaultMaxLen?: number;
|
|
176
176
|
/** Max JSON request body in bytes. Default 32768. */
|
|
177
177
|
bodyCap?: number;
|
|
178
|
+
/** Reject a submit that carries no truthy `disclaimerAck` (400), instead of
|
|
179
|
+
* writing a row with no consent record. Default `false` for back-compat —
|
|
180
|
+
* but turn it on if the disclaimer is a compliance record: a missing ack is
|
|
181
|
+
* otherwise silent, permanent and unreconstructible. Failure is deterministic
|
|
182
|
+
* and surfaces on the first test submit, not intermittently in production. */
|
|
183
|
+
requireDisclaimerAck?: boolean;
|
|
178
184
|
}
|
|
179
185
|
/** The fully-resolved application config carried on the {@link Chapter}. */
|
|
180
186
|
interface ResolvedApplication {
|
|
@@ -183,6 +189,7 @@ interface ResolvedApplication {
|
|
|
183
189
|
maxLen: Record<string, number>;
|
|
184
190
|
defaultMaxLen: number;
|
|
185
191
|
bodyCap: number;
|
|
192
|
+
requireDisclaimerAck: boolean;
|
|
186
193
|
}
|
|
187
194
|
/** The `defineChapter()` config a site fills in. */
|
|
188
195
|
interface ChapterConfig {
|
|
@@ -625,6 +632,9 @@ declare function canceledPatch(): {
|
|
|
625
632
|
|
|
626
633
|
/** Apply defaults + validate the application config. Throws at import on bad shape. */
|
|
627
634
|
declare function resolveApplication(a: ChapterApplication | undefined): ResolvedApplication;
|
|
635
|
+
/** Whether a submit body carries a genuine disclaimer acknowledgement. Accepts
|
|
636
|
+
* the boolean an API client sends and the string a plain HTML form posts. */
|
|
637
|
+
declare function hasDisclaimerAck(fields: Record<string, unknown>): boolean;
|
|
628
638
|
/**
|
|
629
639
|
* The applicant profile written to the Clerk account's `public_metadata.profile`:
|
|
630
640
|
* every configured application field Clerk does not already carry natively, plus
|
|
@@ -633,12 +643,17 @@ declare function resolveApplication(a: ChapterApplication | undefined): Resolved
|
|
|
633
643
|
* there is nothing to write.
|
|
634
644
|
*/
|
|
635
645
|
declare function applicantProfile(chapter: Chapter, fields: Record<string, unknown>): Record<string, unknown> | undefined;
|
|
636
|
-
/** A validated submission, or a 400-worthy validation error the route returns.
|
|
646
|
+
/** A validated submission, or a 400-worthy validation error the route returns.
|
|
647
|
+
* `disclaimerAckAt` reports what THIS request recorded — a number when consent
|
|
648
|
+
* was stamped, `null` when none was supplied. It is always present so a missing
|
|
649
|
+
* consent record is visible in the response rather than silently absent from a
|
|
650
|
+
* row nobody reads until an audit. */
|
|
637
651
|
type SubmitResult = {
|
|
638
652
|
ok: true;
|
|
639
653
|
id: string;
|
|
640
654
|
duplicate: boolean;
|
|
641
655
|
status: string;
|
|
656
|
+
disclaimerAckAt: number | null;
|
|
642
657
|
} | {
|
|
643
658
|
ok: false;
|
|
644
659
|
error: string;
|
|
@@ -1016,4 +1031,4 @@ type ApplicationBookingPatch = {
|
|
|
1016
1031
|
* already there (never backward). */
|
|
1017
1032
|
declare function applicationBookingUpdate(currentStatus: string, startAt: number, htmlLink?: string | null): ApplicationBookingPatch;
|
|
1018
1033
|
|
|
1019
|
-
export { type AccountModel, type AdminNotificationTrigger, type Applicant, type ApplicationBookingPatch, type ApplicationRecord, type ApplicationSummary, type Attr, type AttrType, type Chapter, type ChapterApplication, type ChapterAuth, type ChapterBrand, type ChapterConfig, type ChapterDb, type ChapterEmails, type ChapterIntegrationDescriptor, type ChapterIntegrationOptions, type ChapterMode, type ChapterPipeline, type ChapterPolicy, type ChapterPrices, type ChapterScheduling, type ChapterSends, type ClerkInviteInput, type ClerkResult, type ClerkUserInput, type DbOp, type DbRules, type DbSchema, type DeliveryDecision, type EmailGroup, type EmailTemplate, type EmailTemplateRow, type Entity, type ExistingMeeting, type GuardResult, type JoinConfigGroup, type LiveEvent, type MailSender, type MeetingForReconcile, type MeetingRecord, type MeetingReschedulePatch, type MemberApplication, type MemberSession, type NewMeetingRow, type NotifyDeps, type NotifyInput, type NotifyResult, type PaymentsGroup, type ProjectionDeps, type ReconcileDecision, type ResolvedApplication, type ResolvedAuth, type ResolvedPipeline, type ResolvedScheduling, type ResolvedSends, type RoleChangeContext, type Rule, SCHEDULING_DEFAULTS, type SchedulingErrors, type SecretStore, type SessionUser, type SharedPerson, type StripeEvent, type SubmitResult, type WebhookEvent, applicantProfile, applicationBookingUpdate, applicationSummary, bookingDecision, brandTokens, buildGroupSeed, canApprove, canBook, canChangeRole, canTransition, canceledPatch, chapterDb, clerkInviteRequest, clerkUserRequest, createChapterIntegration, createClerkInvitation, createClerkUser, defaultCrm, defineChapter, emailGroupFrom, endForSlot, findApplicationRef, firstPaymentPatch, getVaultSecret, introIdempotencyKey, isAdminRole, isAlreadySent, isReconcilable, isSlotAvailable, joinConfig, meetingCreateRow, meetingRescheduleUpdate, memberApplication, memberSession, normalizeWebhookEvent, paymentsReady, planDelivery, projectApplicant, projectSharedRecord, reconcileMeetings, refundedPatch, render, renderSummary, renderTemplateBody, renewalPatch, resolveApplication, resolveAuth, resolvePipeline, resolveScheduling, roleFromClaim, sendTemplated, sharedPersonInput, slotWindow, stageIndex, stripeForm, submitApplication, subscriptionIdempotencyKey, validateScheduling, verifyStripeSignature, webhookMutationId };
|
|
1034
|
+
export { type AccountModel, type AdminNotificationTrigger, type Applicant, type ApplicationBookingPatch, type ApplicationRecord, type ApplicationSummary, type Attr, type AttrType, type Chapter, type ChapterApplication, type ChapterAuth, type ChapterBrand, type ChapterConfig, type ChapterDb, type ChapterEmails, type ChapterIntegrationDescriptor, type ChapterIntegrationOptions, type ChapterMode, type ChapterPipeline, type ChapterPolicy, type ChapterPrices, type ChapterScheduling, type ChapterSends, type ClerkInviteInput, type ClerkResult, type ClerkUserInput, type DbOp, type DbRules, type DbSchema, type DeliveryDecision, type EmailGroup, type EmailTemplate, type EmailTemplateRow, type Entity, type ExistingMeeting, type GuardResult, type JoinConfigGroup, type LiveEvent, type MailSender, type MeetingForReconcile, type MeetingRecord, type MeetingReschedulePatch, type MemberApplication, type MemberSession, type NewMeetingRow, type NotifyDeps, type NotifyInput, type NotifyResult, type PaymentsGroup, type ProjectionDeps, type ReconcileDecision, type ResolvedApplication, type ResolvedAuth, type ResolvedPipeline, type ResolvedScheduling, type ResolvedSends, type RoleChangeContext, type Rule, SCHEDULING_DEFAULTS, type SchedulingErrors, type SecretStore, type SessionUser, type SharedPerson, type StripeEvent, type SubmitResult, type WebhookEvent, applicantProfile, applicationBookingUpdate, applicationSummary, bookingDecision, brandTokens, buildGroupSeed, canApprove, canBook, canChangeRole, canTransition, canceledPatch, chapterDb, clerkInviteRequest, clerkUserRequest, createChapterIntegration, createClerkInvitation, createClerkUser, defaultCrm, defineChapter, emailGroupFrom, endForSlot, findApplicationRef, firstPaymentPatch, getVaultSecret, hasDisclaimerAck, introIdempotencyKey, isAdminRole, isAlreadySent, isReconcilable, isSlotAvailable, joinConfig, meetingCreateRow, meetingRescheduleUpdate, memberApplication, memberSession, normalizeWebhookEvent, paymentsReady, planDelivery, projectApplicant, projectSharedRecord, reconcileMeetings, refundedPatch, render, renderSummary, renderTemplateBody, renewalPatch, resolveApplication, resolveAuth, resolvePipeline, resolveScheduling, roleFromClaim, sendTemplated, sharedPersonInput, slotWindow, stageIndex, stripeForm, submitApplication, subscriptionIdempotencyKey, validateScheduling, verifyStripeSignature, webhookMutationId };
|
package/dist/index.js
CHANGED
|
@@ -400,9 +400,13 @@ function resolveApplication(a) {
|
|
|
400
400
|
optional,
|
|
401
401
|
maxLen: a?.maxLen ?? {},
|
|
402
402
|
defaultMaxLen: a?.defaultMaxLen ?? 2e3,
|
|
403
|
-
bodyCap: a?.bodyCap ?? 32768
|
|
403
|
+
bodyCap: a?.bodyCap ?? 32768,
|
|
404
|
+
requireDisclaimerAck: a?.requireDisclaimerAck ?? false
|
|
404
405
|
};
|
|
405
406
|
}
|
|
407
|
+
function hasDisclaimerAck(fields) {
|
|
408
|
+
return fields.disclaimerAck === true || fields.disclaimerAck === "true";
|
|
409
|
+
}
|
|
406
410
|
var IDENTITY_FIELDS = /* @__PURE__ */ new Set(["email", "firstName", "lastName"]);
|
|
407
411
|
function applicantProfile(chapter, fields) {
|
|
408
412
|
const profile = {};
|
|
@@ -425,6 +429,10 @@ async function submitApplication(db, chapter, fields, opts) {
|
|
|
425
429
|
const cap = app.maxLen[f] ?? app.defaultMaxLen;
|
|
426
430
|
if (typeof v === "string" && v.length > cap) return { ok: false, error: `${f} exceeds ${cap} characters` };
|
|
427
431
|
}
|
|
432
|
+
const acked = hasDisclaimerAck(fields);
|
|
433
|
+
if (app.requireDisclaimerAck && !acked) {
|
|
434
|
+
return { ok: false, error: "disclaimerAck is required" };
|
|
435
|
+
}
|
|
428
436
|
const id2 = opts.newId();
|
|
429
437
|
const row = { id: id2, status: chapter.pipeline.initial, createdAt: opts.now };
|
|
430
438
|
for (const f of [...app.required, ...app.optional]) {
|
|
@@ -432,12 +440,12 @@ async function submitApplication(db, chapter, fields, opts) {
|
|
|
432
440
|
}
|
|
433
441
|
if (fields.focus !== void 0) row.focus = fields.focus;
|
|
434
442
|
if (opts.groupId) row.groupId = opts.groupId;
|
|
435
|
-
if (
|
|
443
|
+
if (acked) row.disclaimerAckAt = opts.now;
|
|
436
444
|
const { duplicate } = await db.transact(
|
|
437
445
|
[{ t: "update", ns: "applications", id: id2, attrs: row }],
|
|
438
446
|
opts.submissionId ? { mutationId: `join:${opts.submissionId}` } : void 0
|
|
439
447
|
);
|
|
440
|
-
return { ok: true, id: id2, duplicate, status: chapter.pipeline.initial };
|
|
448
|
+
return { ok: true, id: id2, duplicate, status: chapter.pipeline.initial, disclaimerAckAt: acked ? opts.now : null };
|
|
441
449
|
}
|
|
442
450
|
function joinConfig(group, paymentsReady2) {
|
|
443
451
|
return {
|
|
@@ -1073,6 +1081,7 @@ export {
|
|
|
1073
1081
|
findApplicationRef,
|
|
1074
1082
|
firstPaymentPatch,
|
|
1075
1083
|
getVaultSecret,
|
|
1084
|
+
hasDisclaimerAck,
|
|
1076
1085
|
introIdempotencyKey,
|
|
1077
1086
|
isAdminRole,
|
|
1078
1087
|
isAlreadySent,
|