@odla-ai/chapter 0.34.0 → 0.36.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 +83 -2
- package/dist/{chunk-UJIVBGL5.js → chunk-I45VYBUV.js} +441 -239
- package/dist/chunk-I45VYBUV.js.map +1 -0
- package/dist/{chunk-JAWTIROV.js → chunk-IAWBE5PX.js} +55 -1
- package/dist/chunk-IAWBE5PX.js.map +1 -0
- package/dist/{chunk-TXE5ZDI4.js → chunk-LWM32REV.js} +166 -59
- package/dist/chunk-LWM32REV.js.map +1 -0
- package/dist/{copy-context-c1tqPXOR.d.ts → copy-context-0k0-yWHL.d.ts} +6 -2
- package/dist/index.cjs +967 -296
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +253 -3
- package/dist/index.d.ts +253 -3
- package/dist/index.js +967 -296
- package/dist/index.js.map +1 -1
- package/dist/ui/admin/index.d.ts +10 -3
- package/dist/ui/admin/index.js +6 -2
- package/dist/ui/index.d.ts +3 -3
- package/dist/ui/index.js +11 -3
- package/dist/ui/member/index.d.ts +86 -7
- package/dist/ui/member/index.js +6 -2
- package/dist/worker/index.cjs +1957 -722
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.d.cts +200 -3
- package/dist/worker/index.d.ts +200 -3
- package/dist/worker/index.js +1968 -733
- package/dist/worker/index.js.map +1 -1
- package/package.json +2 -1
- package/dist/chunk-JAWTIROV.js.map +0 -1
- package/dist/chunk-TXE5ZDI4.js.map +0 -1
- package/dist/chunk-UJIVBGL5.js.map +0 -1
package/dist/worker/index.d.cts
CHANGED
|
@@ -43,18 +43,21 @@ interface ChapterCopy {
|
|
|
43
43
|
*/
|
|
44
44
|
payment: TextFields<"setupFailed" | "preparing" | "pending" | "processing" | "payAndContinue" | "incomplete" | "consent">;
|
|
45
45
|
done: TextFields<"label" | "calendarInvite" | "memberArea">;
|
|
46
|
+
accepted: TextFields<"label" | "body">;
|
|
47
|
+
gift: TextFields<"chooseSelf" | "optionsLabel" | "label" | "body" | "save" | "rotate" | "rotateFailed">;
|
|
46
48
|
};
|
|
47
49
|
members: {
|
|
48
50
|
loadFailed: string;
|
|
49
51
|
account: TextFields<"signOut" | "adminConsole">;
|
|
50
52
|
provisional: TextFields<"cardLabel" | "applicationNeeded" | "applicationNeededBody" | "apply" | "refunded" | "refundedBody" | "active" | "renews" | "introductionCall" | "calendarInvite" | "joinCall" | "bookCall" | "bookCallBody" | "chooseTime">;
|
|
51
53
|
full: TextFields<"welcome">;
|
|
54
|
+
gifts: TextFields<"title" | "body" | "noneAvailable" | "paid" | "saveCode" | "purchases" | "noPurchases" | "pending" | "redeemed" | "expired" | "revoked" | "rotate" | "rotated" | "rotateFailed" | "redeemTitle" | "code" | "redeem" | "redeemFailed">;
|
|
52
55
|
reschedule: TextFields<"changeTime" | "unavailable" | "loadFailed" | "slotGone" | "loading" | "noTimes" | "rescheduling" | "keepTime">;
|
|
53
56
|
};
|
|
54
57
|
admin: {
|
|
55
58
|
auth: TextFields<"checking" | "notAuthorized" | "accountNotAuthorized" | "thisAccount" | "signOut" | "loading" | "signInNotConfigured" | "missingPublishableKey" | "noWorkspaces" | "signInTagline">;
|
|
56
59
|
shell: TextFields<"adminRole" | "adminConsole" | "adminName" | "navigationLabel">;
|
|
57
|
-
workspaces: TextFields<"dashboard" | "overview" | "billing" | "people" | "network" | "portfolio" | "settings" | "calendar" | "email" | "chapters" | "formations" | "dealFlow" | "dashboardViewsLabel" | "settingsViewsLabel" | "collectionsLabel" | "portfolioViewsLabel">;
|
|
60
|
+
workspaces: TextFields<"dashboard" | "overview" | "billing" | "people" | "admission" | "network" | "portfolio" | "settings" | "calendar" | "email" | "chapters" | "formations" | "dealFlow" | "dashboardViewsLabel" | "settingsViewsLabel" | "collectionsLabel" | "portfolioViewsLabel">;
|
|
58
61
|
dashboard: TextFields<"loading" | "loadFailed" | "upcomingCalls" | "callsNeedAttention" | "noUpcomingCalls" | "drift" | "open" | "meet" | "applications" | "newMembers" | "newMembersUnavailable" | "revenueAdded" | "revenue" | "revenueUnavailable" | "pipeline" | "pipelineLabel" | "thisWeek" | "noChange" | "activeMemberships" | "annualRunRate" | "testMode">;
|
|
59
62
|
billing: TextFields<"loading" | "loadFailed" | "notConfigured" | "active" | "annualized" | "renewingSoon" | "pastDue" | "subscriptions" | "testMode" | "truncated" | "name" | "email" | "application" | "subscription" | "cancelling" | "amount" | "renews">;
|
|
60
63
|
availability: TextFields<"loading" | "loadFailed" | "saved" | "title" | "days" | "startHour" | "endHour" | "slotMinutes" | "minNoticeHours" | "windowDays" | "timezone" | "summaryTemplate" | "save"> & {
|
|
@@ -62,6 +65,7 @@ interface ChapterCopy {
|
|
|
62
65
|
};
|
|
63
66
|
email: TextFields<"loading" | "loadFailed" | "saved" | "sent" | "testFailed" | "delivery" | "notificationAddress" | "replyTo" | "debugInbox" | "debugInboxHint" | "sendTest" | "enabled" | "subject" | "body" | "save" | "sendLog" | "sentColumn" | "templateColumn" | "statusColumn" | "toColumn" | "failed" | "redirected" | "delivered">;
|
|
64
67
|
meetings: TextFields<"loading" | "loadFailed" | "cancelConfirm" | "newStartPrompt" | "parseFailed" | "agenda" | "empty" | "unknown" | "drift" | "meet" | "reschedule" | "cancel">;
|
|
68
|
+
admission: TextFields<"title" | "description" | "email" | "decision" | "expires" | "note" | "waive" | "require" | "add" | "ledger" | "loading" | "consumed" | "revoked" | "expired" | "active" | "local" | "parent" | "revoke">;
|
|
65
69
|
network: AdminNetworkCopy;
|
|
66
70
|
records: TextFields<"workflowMissing" | "comms" | "commsHistory" | "scheduling" | "billing" | "notes" | "access" | "sharing" | "lifecycle" | "role" | "superAdminHint" | "noAccount" | "approve" | "refund" | "approved" | "refunded" | "roleSet" | "messageSent" | "messageNotSent" | "loadingTemplates" | "template" | "chooseTemplate" | "sending" | "send" | "noMessages" | "message" | "newStartPrompt" | "parseFailed" | "cancelConfirm" | "callCancelled" | "callRescheduled" | "noApplication" | "loadingMeetings" | "noMeetings" | "joinMeeting" | "openCalendar" | "reschedule" | "cancel">;
|
|
67
71
|
};
|
|
@@ -209,7 +213,64 @@ interface ChapterPolicy {
|
|
|
209
213
|
* (join, Stripe membership, booking, member area, admin, CRM); `hub` is
|
|
210
214
|
* admin-only and CRM-focused (a directory/registry over the same CRM). */
|
|
211
215
|
type ChapterMode = "chapter" | "hub";
|
|
212
|
-
/**
|
|
216
|
+
/** One odla-db transaction op — the wire shape both the real admin client and a
|
|
217
|
+
* test double (`FakeDb`) accept. Built as a plain object, never via a `tx` proxy. */
|
|
218
|
+
type DbOp<Id extends string | {
|
|
219
|
+
ns: string;
|
|
220
|
+
attr: string;
|
|
221
|
+
value: string | number | boolean;
|
|
222
|
+
} = string> = {
|
|
223
|
+
t: "update" | "merge";
|
|
224
|
+
ns: string;
|
|
225
|
+
id: Id;
|
|
226
|
+
attrs: Record<string, unknown>;
|
|
227
|
+
} | {
|
|
228
|
+
t: "retract";
|
|
229
|
+
ns: string;
|
|
230
|
+
id: Id;
|
|
231
|
+
attrs: string[];
|
|
232
|
+
} | {
|
|
233
|
+
t: "delete";
|
|
234
|
+
ns: string;
|
|
235
|
+
id: Id;
|
|
236
|
+
attrs?: undefined;
|
|
237
|
+
};
|
|
238
|
+
/** The structural view of the odla-db admin client the worker builds and the
|
|
239
|
+
* member routes consume — so route logic is testable against an in-memory fake. */
|
|
240
|
+
interface ChapterDb {
|
|
241
|
+
query(q: Record<string, unknown>): Promise<Record<string, Array<Record<string, unknown>>>>;
|
|
242
|
+
/** Optional bounded aggregate supported by the real privileged odla-db
|
|
243
|
+
* client. Routes use it to prove a result set is non-empty before issuing
|
|
244
|
+
* an ordered lookup, while small test doubles may continue to omit it. */
|
|
245
|
+
aggregate?(ns: string, spec: {
|
|
246
|
+
count?: boolean;
|
|
247
|
+
}, opts?: {
|
|
248
|
+
where?: Record<string, unknown>;
|
|
249
|
+
}): Promise<{
|
|
250
|
+
count?: number;
|
|
251
|
+
}>;
|
|
252
|
+
transact(ops: DbOp<string | {
|
|
253
|
+
ns: string;
|
|
254
|
+
attr: string;
|
|
255
|
+
value: string | number | boolean;
|
|
256
|
+
}>[], opts?: {
|
|
257
|
+
mutationId?: string;
|
|
258
|
+
guards?: Array<{
|
|
259
|
+
ns: string;
|
|
260
|
+
id: string;
|
|
261
|
+
exists: boolean;
|
|
262
|
+
equals?: Record<string, unknown>;
|
|
263
|
+
absent?: string[];
|
|
264
|
+
}>;
|
|
265
|
+
}): Promise<{
|
|
266
|
+
txId: number;
|
|
267
|
+
duplicate: boolean;
|
|
268
|
+
}>;
|
|
269
|
+
secrets: {
|
|
270
|
+
get(name: string): Promise<string>;
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
/** Scalar kinds accepted by the Chapter schema adapter. */
|
|
213
274
|
type AttrType = "string" | "number" | "boolean" | "json";
|
|
214
275
|
/** One odla-db attribute: its type and index/uniqueness/optionality flags. */
|
|
215
276
|
interface Attr {
|
|
@@ -709,6 +770,37 @@ interface MembershipPageDocument {
|
|
|
709
770
|
footnoteMarkdown?: string;
|
|
710
771
|
}
|
|
711
772
|
|
|
773
|
+
/** Current nested gift-catalog version inside signup-control. */
|
|
774
|
+
declare const GIFT_OFFER_CATALOG_VERSION: 1;
|
|
775
|
+
/** Membership tier or standalone entitlement fulfilled by redemption. */
|
|
776
|
+
type GiftOfferTarget = {
|
|
777
|
+
type: "tier";
|
|
778
|
+
tierId: string;
|
|
779
|
+
} | {
|
|
780
|
+
type: "entitlement";
|
|
781
|
+
entitlementKey: string;
|
|
782
|
+
};
|
|
783
|
+
/** Server-authored gift SKU; provider identifiers never reach public config. */
|
|
784
|
+
interface GiftOffer {
|
|
785
|
+
id: string;
|
|
786
|
+
target: GiftOfferTarget;
|
|
787
|
+
billingMode: "one_time" | "subscription";
|
|
788
|
+
stripePriceId: string;
|
|
789
|
+
priceCents: number;
|
|
790
|
+
currency: string;
|
|
791
|
+
redemptionLifetimeHours: number;
|
|
792
|
+
activeFrom?: number;
|
|
793
|
+
activeUntil?: number;
|
|
794
|
+
title: string;
|
|
795
|
+
description: string;
|
|
796
|
+
ctaLabel: string;
|
|
797
|
+
}
|
|
798
|
+
/** Versioned bounded collection delegated through signed signup control. */
|
|
799
|
+
interface GiftOfferCatalog {
|
|
800
|
+
schemaVersion: typeof GIFT_OFFER_CATALOG_VERSION;
|
|
801
|
+
offers: readonly GiftOffer[];
|
|
802
|
+
}
|
|
803
|
+
|
|
712
804
|
/** Current wire-format version for complete signup-control documents. */
|
|
713
805
|
declare const SIGNUP_CONTROL_SCHEMA_VERSION: 1;
|
|
714
806
|
/** One authoritative membership tier in a signup-control revision. */
|
|
@@ -760,6 +852,7 @@ interface SignupControlDocument {
|
|
|
760
852
|
policy?: SignupControlPolicy;
|
|
761
853
|
scheduling?: ChapterScheduling;
|
|
762
854
|
theme?: SignupControlTheme;
|
|
855
|
+
giftOffers?: GiftOfferCatalog;
|
|
763
856
|
}
|
|
764
857
|
/** Digest travels beside the document so the exact desired state is attestable. */
|
|
765
858
|
interface SignupControlEnvelope {
|
|
@@ -790,6 +883,110 @@ interface SignupControlDeliveryOptions {
|
|
|
790
883
|
/** Build and send one signed desired-state delivery. Durable retry belongs to the hub outbox. */
|
|
791
884
|
declare function deliverSignupControl(options: SignupControlDeliveryOptions): Promise<SignupControlReceipt>;
|
|
792
885
|
|
|
886
|
+
/** Current wire version for parent-authored admission decisions. */
|
|
887
|
+
declare const ADMISSION_GRANTS_SCHEMA_VERSION: 1;
|
|
888
|
+
/** Whether an exact email can skip or must retain the Chapter interview. */
|
|
889
|
+
type AdmissionDecision = "waive_interview" | "require_interview";
|
|
890
|
+
/** One bounded admission decision. Email is PII and never enters public config. */
|
|
891
|
+
interface AdmissionGrantInput {
|
|
892
|
+
id: string;
|
|
893
|
+
email: string;
|
|
894
|
+
decision: AdmissionDecision;
|
|
895
|
+
note?: string;
|
|
896
|
+
expiresAt?: number;
|
|
897
|
+
}
|
|
898
|
+
/** Complete desired Parent state for one Chapter and environment. */
|
|
899
|
+
interface AdmissionGrantDocument {
|
|
900
|
+
schemaVersion: typeof ADMISSION_GRANTS_SCHEMA_VERSION;
|
|
901
|
+
revision: number;
|
|
902
|
+
generatedAt: number;
|
|
903
|
+
source: {
|
|
904
|
+
appId: string;
|
|
905
|
+
actor: string;
|
|
906
|
+
};
|
|
907
|
+
target: {
|
|
908
|
+
chapterId: string;
|
|
909
|
+
environment: string;
|
|
910
|
+
};
|
|
911
|
+
grants: readonly AdmissionGrantInput[];
|
|
912
|
+
}
|
|
913
|
+
/** Canonical desired-state document paired with its integrity digest. */
|
|
914
|
+
interface AdmissionGrantEnvelope {
|
|
915
|
+
digest: string;
|
|
916
|
+
document: AdmissionGrantDocument;
|
|
917
|
+
}
|
|
918
|
+
/** Chapter acknowledgement for an accepted or idempotently replayed revision. */
|
|
919
|
+
interface AdmissionGrantReceipt {
|
|
920
|
+
ok: true;
|
|
921
|
+
target: {
|
|
922
|
+
chapterId: string;
|
|
923
|
+
environment: string;
|
|
924
|
+
};
|
|
925
|
+
revision: number;
|
|
926
|
+
digest: string;
|
|
927
|
+
status: "accepted" | "replayed";
|
|
928
|
+
acknowledgedAt: number;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/** Inputs required to sign and deliver one Parent admission revision. */
|
|
932
|
+
interface AdmissionGrantDeliveryOptions {
|
|
933
|
+
secret: string;
|
|
934
|
+
sender: string;
|
|
935
|
+
targetUrl: string | URL;
|
|
936
|
+
envelope: AdmissionGrantEnvelope;
|
|
937
|
+
fetch?: typeof globalThis.fetch;
|
|
938
|
+
}
|
|
939
|
+
/** Deliver one signed Parent admission revision. Durable retry belongs upstream. */
|
|
940
|
+
declare function deliverAdmissionGrants(options: AdmissionGrantDeliveryOptions): Promise<AdmissionGrantReceipt>;
|
|
941
|
+
|
|
942
|
+
/** Identity shared by initial HTML, response caching, and client hydration. */
|
|
943
|
+
interface SignupControlThemeMetadata {
|
|
944
|
+
source: "active" | "bootstrap";
|
|
945
|
+
revision: number | null;
|
|
946
|
+
digest: string | null;
|
|
947
|
+
/** Include this value in any host-owned cache key for transformed HTML. */
|
|
948
|
+
cacheKey: string;
|
|
949
|
+
}
|
|
950
|
+
/** A validated style block ready to place in an HTML head. */
|
|
951
|
+
interface SignupControlThemeHead {
|
|
952
|
+
css: string;
|
|
953
|
+
head: string;
|
|
954
|
+
metadata: SignupControlThemeMetadata;
|
|
955
|
+
}
|
|
956
|
+
/** Host-owned fallback inputs shared by server rendering and hydration. */
|
|
957
|
+
interface SignupControlThemeOptions {
|
|
958
|
+
/** Local site-owned tokens used only when no active managed revision exists. */
|
|
959
|
+
bootstrapTokens?: Readonly<Record<string, string | number>>;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/** Inputs required to resolve one follower-local active signup theme. */
|
|
963
|
+
interface ActiveSignupControlThemeOptions extends SignupControlThemeOptions {
|
|
964
|
+
/** Follower-local database client. No controlling-hub request is performed. */
|
|
965
|
+
db: ChapterDb;
|
|
966
|
+
chapterId: string;
|
|
967
|
+
environment: string;
|
|
968
|
+
/** Optional host marker; defaults to `SIGNUP_CONTROL_THEME_MARKER`. */
|
|
969
|
+
marker?: string;
|
|
970
|
+
}
|
|
971
|
+
/** Transformed HTML plus the exact theme and cache identity it contains. */
|
|
972
|
+
interface ActiveSignupControlHtml {
|
|
973
|
+
html: string;
|
|
974
|
+
theme: SignupControlThemeHead;
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* Transform trusted host HTML with the follower-local last-known-good signup
|
|
978
|
+
* theme. A missing active revision uses the documented bootstrap state; a read
|
|
979
|
+
* failure or corrupt active row fails closed instead of fetching the hub.
|
|
980
|
+
*/
|
|
981
|
+
declare function renderActiveSignupControlHtml(html: string, options: ActiveSignupControlThemeOptions): Promise<ActiveSignupControlHtml>;
|
|
982
|
+
/**
|
|
983
|
+
* Transform an HTML response and make the cache contract safe by default.
|
|
984
|
+
* `no-store` prevents a prior digest from surviving activation; hosts that own
|
|
985
|
+
* a cache may instead key it with `result.theme.metadata.cacheKey` from
|
|
986
|
+
* {@link renderActiveSignupControlHtml}.
|
|
987
|
+
*/
|
|
988
|
+
declare function withActiveSignupControlTheme(response: Response, options: ActiveSignupControlThemeOptions): Promise<Response>;
|
|
989
|
+
|
|
793
990
|
/**
|
|
794
991
|
* Build the Cloudflare `ExportedHandler` for a chapter/hub site: Clerk-JWT
|
|
795
992
|
* verification, the source-aware admin gate, the mounted @odla-ai/crm routes, the
|
|
@@ -812,4 +1009,4 @@ declare function chapterWorker(options: ChapterWorkerOptions): {
|
|
|
812
1009
|
fetch(req: Request, env: ChapterEnv): Promise<Response>;
|
|
813
1010
|
};
|
|
814
1011
|
|
|
815
|
-
export { type ChapterEnv, type ChapterWorkerOptions, type Route, type SignupControlDeliveryOptions, type WorkerContext, chapterWorker, createWorkerContext, deliverSignupControl };
|
|
1012
|
+
export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, type AdmissionGrantDeliveryOptions, type ChapterEnv, type ChapterWorkerOptions, type Route, type SignupControlDeliveryOptions, type WorkerContext, chapterWorker, createWorkerContext, deliverAdmissionGrants, deliverSignupControl, renderActiveSignupControlHtml, withActiveSignupControlTheme };
|
package/dist/worker/index.d.ts
CHANGED
|
@@ -43,18 +43,21 @@ interface ChapterCopy {
|
|
|
43
43
|
*/
|
|
44
44
|
payment: TextFields<"setupFailed" | "preparing" | "pending" | "processing" | "payAndContinue" | "incomplete" | "consent">;
|
|
45
45
|
done: TextFields<"label" | "calendarInvite" | "memberArea">;
|
|
46
|
+
accepted: TextFields<"label" | "body">;
|
|
47
|
+
gift: TextFields<"chooseSelf" | "optionsLabel" | "label" | "body" | "save" | "rotate" | "rotateFailed">;
|
|
46
48
|
};
|
|
47
49
|
members: {
|
|
48
50
|
loadFailed: string;
|
|
49
51
|
account: TextFields<"signOut" | "adminConsole">;
|
|
50
52
|
provisional: TextFields<"cardLabel" | "applicationNeeded" | "applicationNeededBody" | "apply" | "refunded" | "refundedBody" | "active" | "renews" | "introductionCall" | "calendarInvite" | "joinCall" | "bookCall" | "bookCallBody" | "chooseTime">;
|
|
51
53
|
full: TextFields<"welcome">;
|
|
54
|
+
gifts: TextFields<"title" | "body" | "noneAvailable" | "paid" | "saveCode" | "purchases" | "noPurchases" | "pending" | "redeemed" | "expired" | "revoked" | "rotate" | "rotated" | "rotateFailed" | "redeemTitle" | "code" | "redeem" | "redeemFailed">;
|
|
52
55
|
reschedule: TextFields<"changeTime" | "unavailable" | "loadFailed" | "slotGone" | "loading" | "noTimes" | "rescheduling" | "keepTime">;
|
|
53
56
|
};
|
|
54
57
|
admin: {
|
|
55
58
|
auth: TextFields<"checking" | "notAuthorized" | "accountNotAuthorized" | "thisAccount" | "signOut" | "loading" | "signInNotConfigured" | "missingPublishableKey" | "noWorkspaces" | "signInTagline">;
|
|
56
59
|
shell: TextFields<"adminRole" | "adminConsole" | "adminName" | "navigationLabel">;
|
|
57
|
-
workspaces: TextFields<"dashboard" | "overview" | "billing" | "people" | "network" | "portfolio" | "settings" | "calendar" | "email" | "chapters" | "formations" | "dealFlow" | "dashboardViewsLabel" | "settingsViewsLabel" | "collectionsLabel" | "portfolioViewsLabel">;
|
|
60
|
+
workspaces: TextFields<"dashboard" | "overview" | "billing" | "people" | "admission" | "network" | "portfolio" | "settings" | "calendar" | "email" | "chapters" | "formations" | "dealFlow" | "dashboardViewsLabel" | "settingsViewsLabel" | "collectionsLabel" | "portfolioViewsLabel">;
|
|
58
61
|
dashboard: TextFields<"loading" | "loadFailed" | "upcomingCalls" | "callsNeedAttention" | "noUpcomingCalls" | "drift" | "open" | "meet" | "applications" | "newMembers" | "newMembersUnavailable" | "revenueAdded" | "revenue" | "revenueUnavailable" | "pipeline" | "pipelineLabel" | "thisWeek" | "noChange" | "activeMemberships" | "annualRunRate" | "testMode">;
|
|
59
62
|
billing: TextFields<"loading" | "loadFailed" | "notConfigured" | "active" | "annualized" | "renewingSoon" | "pastDue" | "subscriptions" | "testMode" | "truncated" | "name" | "email" | "application" | "subscription" | "cancelling" | "amount" | "renews">;
|
|
60
63
|
availability: TextFields<"loading" | "loadFailed" | "saved" | "title" | "days" | "startHour" | "endHour" | "slotMinutes" | "minNoticeHours" | "windowDays" | "timezone" | "summaryTemplate" | "save"> & {
|
|
@@ -62,6 +65,7 @@ interface ChapterCopy {
|
|
|
62
65
|
};
|
|
63
66
|
email: TextFields<"loading" | "loadFailed" | "saved" | "sent" | "testFailed" | "delivery" | "notificationAddress" | "replyTo" | "debugInbox" | "debugInboxHint" | "sendTest" | "enabled" | "subject" | "body" | "save" | "sendLog" | "sentColumn" | "templateColumn" | "statusColumn" | "toColumn" | "failed" | "redirected" | "delivered">;
|
|
64
67
|
meetings: TextFields<"loading" | "loadFailed" | "cancelConfirm" | "newStartPrompt" | "parseFailed" | "agenda" | "empty" | "unknown" | "drift" | "meet" | "reschedule" | "cancel">;
|
|
68
|
+
admission: TextFields<"title" | "description" | "email" | "decision" | "expires" | "note" | "waive" | "require" | "add" | "ledger" | "loading" | "consumed" | "revoked" | "expired" | "active" | "local" | "parent" | "revoke">;
|
|
65
69
|
network: AdminNetworkCopy;
|
|
66
70
|
records: TextFields<"workflowMissing" | "comms" | "commsHistory" | "scheduling" | "billing" | "notes" | "access" | "sharing" | "lifecycle" | "role" | "superAdminHint" | "noAccount" | "approve" | "refund" | "approved" | "refunded" | "roleSet" | "messageSent" | "messageNotSent" | "loadingTemplates" | "template" | "chooseTemplate" | "sending" | "send" | "noMessages" | "message" | "newStartPrompt" | "parseFailed" | "cancelConfirm" | "callCancelled" | "callRescheduled" | "noApplication" | "loadingMeetings" | "noMeetings" | "joinMeeting" | "openCalendar" | "reschedule" | "cancel">;
|
|
67
71
|
};
|
|
@@ -209,7 +213,64 @@ interface ChapterPolicy {
|
|
|
209
213
|
* (join, Stripe membership, booking, member area, admin, CRM); `hub` is
|
|
210
214
|
* admin-only and CRM-focused (a directory/registry over the same CRM). */
|
|
211
215
|
type ChapterMode = "chapter" | "hub";
|
|
212
|
-
/**
|
|
216
|
+
/** One odla-db transaction op — the wire shape both the real admin client and a
|
|
217
|
+
* test double (`FakeDb`) accept. Built as a plain object, never via a `tx` proxy. */
|
|
218
|
+
type DbOp<Id extends string | {
|
|
219
|
+
ns: string;
|
|
220
|
+
attr: string;
|
|
221
|
+
value: string | number | boolean;
|
|
222
|
+
} = string> = {
|
|
223
|
+
t: "update" | "merge";
|
|
224
|
+
ns: string;
|
|
225
|
+
id: Id;
|
|
226
|
+
attrs: Record<string, unknown>;
|
|
227
|
+
} | {
|
|
228
|
+
t: "retract";
|
|
229
|
+
ns: string;
|
|
230
|
+
id: Id;
|
|
231
|
+
attrs: string[];
|
|
232
|
+
} | {
|
|
233
|
+
t: "delete";
|
|
234
|
+
ns: string;
|
|
235
|
+
id: Id;
|
|
236
|
+
attrs?: undefined;
|
|
237
|
+
};
|
|
238
|
+
/** The structural view of the odla-db admin client the worker builds and the
|
|
239
|
+
* member routes consume — so route logic is testable against an in-memory fake. */
|
|
240
|
+
interface ChapterDb {
|
|
241
|
+
query(q: Record<string, unknown>): Promise<Record<string, Array<Record<string, unknown>>>>;
|
|
242
|
+
/** Optional bounded aggregate supported by the real privileged odla-db
|
|
243
|
+
* client. Routes use it to prove a result set is non-empty before issuing
|
|
244
|
+
* an ordered lookup, while small test doubles may continue to omit it. */
|
|
245
|
+
aggregate?(ns: string, spec: {
|
|
246
|
+
count?: boolean;
|
|
247
|
+
}, opts?: {
|
|
248
|
+
where?: Record<string, unknown>;
|
|
249
|
+
}): Promise<{
|
|
250
|
+
count?: number;
|
|
251
|
+
}>;
|
|
252
|
+
transact(ops: DbOp<string | {
|
|
253
|
+
ns: string;
|
|
254
|
+
attr: string;
|
|
255
|
+
value: string | number | boolean;
|
|
256
|
+
}>[], opts?: {
|
|
257
|
+
mutationId?: string;
|
|
258
|
+
guards?: Array<{
|
|
259
|
+
ns: string;
|
|
260
|
+
id: string;
|
|
261
|
+
exists: boolean;
|
|
262
|
+
equals?: Record<string, unknown>;
|
|
263
|
+
absent?: string[];
|
|
264
|
+
}>;
|
|
265
|
+
}): Promise<{
|
|
266
|
+
txId: number;
|
|
267
|
+
duplicate: boolean;
|
|
268
|
+
}>;
|
|
269
|
+
secrets: {
|
|
270
|
+
get(name: string): Promise<string>;
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
/** Scalar kinds accepted by the Chapter schema adapter. */
|
|
213
274
|
type AttrType = "string" | "number" | "boolean" | "json";
|
|
214
275
|
/** One odla-db attribute: its type and index/uniqueness/optionality flags. */
|
|
215
276
|
interface Attr {
|
|
@@ -709,6 +770,37 @@ interface MembershipPageDocument {
|
|
|
709
770
|
footnoteMarkdown?: string;
|
|
710
771
|
}
|
|
711
772
|
|
|
773
|
+
/** Current nested gift-catalog version inside signup-control. */
|
|
774
|
+
declare const GIFT_OFFER_CATALOG_VERSION: 1;
|
|
775
|
+
/** Membership tier or standalone entitlement fulfilled by redemption. */
|
|
776
|
+
type GiftOfferTarget = {
|
|
777
|
+
type: "tier";
|
|
778
|
+
tierId: string;
|
|
779
|
+
} | {
|
|
780
|
+
type: "entitlement";
|
|
781
|
+
entitlementKey: string;
|
|
782
|
+
};
|
|
783
|
+
/** Server-authored gift SKU; provider identifiers never reach public config. */
|
|
784
|
+
interface GiftOffer {
|
|
785
|
+
id: string;
|
|
786
|
+
target: GiftOfferTarget;
|
|
787
|
+
billingMode: "one_time" | "subscription";
|
|
788
|
+
stripePriceId: string;
|
|
789
|
+
priceCents: number;
|
|
790
|
+
currency: string;
|
|
791
|
+
redemptionLifetimeHours: number;
|
|
792
|
+
activeFrom?: number;
|
|
793
|
+
activeUntil?: number;
|
|
794
|
+
title: string;
|
|
795
|
+
description: string;
|
|
796
|
+
ctaLabel: string;
|
|
797
|
+
}
|
|
798
|
+
/** Versioned bounded collection delegated through signed signup control. */
|
|
799
|
+
interface GiftOfferCatalog {
|
|
800
|
+
schemaVersion: typeof GIFT_OFFER_CATALOG_VERSION;
|
|
801
|
+
offers: readonly GiftOffer[];
|
|
802
|
+
}
|
|
803
|
+
|
|
712
804
|
/** Current wire-format version for complete signup-control documents. */
|
|
713
805
|
declare const SIGNUP_CONTROL_SCHEMA_VERSION: 1;
|
|
714
806
|
/** One authoritative membership tier in a signup-control revision. */
|
|
@@ -760,6 +852,7 @@ interface SignupControlDocument {
|
|
|
760
852
|
policy?: SignupControlPolicy;
|
|
761
853
|
scheduling?: ChapterScheduling;
|
|
762
854
|
theme?: SignupControlTheme;
|
|
855
|
+
giftOffers?: GiftOfferCatalog;
|
|
763
856
|
}
|
|
764
857
|
/** Digest travels beside the document so the exact desired state is attestable. */
|
|
765
858
|
interface SignupControlEnvelope {
|
|
@@ -790,6 +883,110 @@ interface SignupControlDeliveryOptions {
|
|
|
790
883
|
/** Build and send one signed desired-state delivery. Durable retry belongs to the hub outbox. */
|
|
791
884
|
declare function deliverSignupControl(options: SignupControlDeliveryOptions): Promise<SignupControlReceipt>;
|
|
792
885
|
|
|
886
|
+
/** Current wire version for parent-authored admission decisions. */
|
|
887
|
+
declare const ADMISSION_GRANTS_SCHEMA_VERSION: 1;
|
|
888
|
+
/** Whether an exact email can skip or must retain the Chapter interview. */
|
|
889
|
+
type AdmissionDecision = "waive_interview" | "require_interview";
|
|
890
|
+
/** One bounded admission decision. Email is PII and never enters public config. */
|
|
891
|
+
interface AdmissionGrantInput {
|
|
892
|
+
id: string;
|
|
893
|
+
email: string;
|
|
894
|
+
decision: AdmissionDecision;
|
|
895
|
+
note?: string;
|
|
896
|
+
expiresAt?: number;
|
|
897
|
+
}
|
|
898
|
+
/** Complete desired Parent state for one Chapter and environment. */
|
|
899
|
+
interface AdmissionGrantDocument {
|
|
900
|
+
schemaVersion: typeof ADMISSION_GRANTS_SCHEMA_VERSION;
|
|
901
|
+
revision: number;
|
|
902
|
+
generatedAt: number;
|
|
903
|
+
source: {
|
|
904
|
+
appId: string;
|
|
905
|
+
actor: string;
|
|
906
|
+
};
|
|
907
|
+
target: {
|
|
908
|
+
chapterId: string;
|
|
909
|
+
environment: string;
|
|
910
|
+
};
|
|
911
|
+
grants: readonly AdmissionGrantInput[];
|
|
912
|
+
}
|
|
913
|
+
/** Canonical desired-state document paired with its integrity digest. */
|
|
914
|
+
interface AdmissionGrantEnvelope {
|
|
915
|
+
digest: string;
|
|
916
|
+
document: AdmissionGrantDocument;
|
|
917
|
+
}
|
|
918
|
+
/** Chapter acknowledgement for an accepted or idempotently replayed revision. */
|
|
919
|
+
interface AdmissionGrantReceipt {
|
|
920
|
+
ok: true;
|
|
921
|
+
target: {
|
|
922
|
+
chapterId: string;
|
|
923
|
+
environment: string;
|
|
924
|
+
};
|
|
925
|
+
revision: number;
|
|
926
|
+
digest: string;
|
|
927
|
+
status: "accepted" | "replayed";
|
|
928
|
+
acknowledgedAt: number;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/** Inputs required to sign and deliver one Parent admission revision. */
|
|
932
|
+
interface AdmissionGrantDeliveryOptions {
|
|
933
|
+
secret: string;
|
|
934
|
+
sender: string;
|
|
935
|
+
targetUrl: string | URL;
|
|
936
|
+
envelope: AdmissionGrantEnvelope;
|
|
937
|
+
fetch?: typeof globalThis.fetch;
|
|
938
|
+
}
|
|
939
|
+
/** Deliver one signed Parent admission revision. Durable retry belongs upstream. */
|
|
940
|
+
declare function deliverAdmissionGrants(options: AdmissionGrantDeliveryOptions): Promise<AdmissionGrantReceipt>;
|
|
941
|
+
|
|
942
|
+
/** Identity shared by initial HTML, response caching, and client hydration. */
|
|
943
|
+
interface SignupControlThemeMetadata {
|
|
944
|
+
source: "active" | "bootstrap";
|
|
945
|
+
revision: number | null;
|
|
946
|
+
digest: string | null;
|
|
947
|
+
/** Include this value in any host-owned cache key for transformed HTML. */
|
|
948
|
+
cacheKey: string;
|
|
949
|
+
}
|
|
950
|
+
/** A validated style block ready to place in an HTML head. */
|
|
951
|
+
interface SignupControlThemeHead {
|
|
952
|
+
css: string;
|
|
953
|
+
head: string;
|
|
954
|
+
metadata: SignupControlThemeMetadata;
|
|
955
|
+
}
|
|
956
|
+
/** Host-owned fallback inputs shared by server rendering and hydration. */
|
|
957
|
+
interface SignupControlThemeOptions {
|
|
958
|
+
/** Local site-owned tokens used only when no active managed revision exists. */
|
|
959
|
+
bootstrapTokens?: Readonly<Record<string, string | number>>;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/** Inputs required to resolve one follower-local active signup theme. */
|
|
963
|
+
interface ActiveSignupControlThemeOptions extends SignupControlThemeOptions {
|
|
964
|
+
/** Follower-local database client. No controlling-hub request is performed. */
|
|
965
|
+
db: ChapterDb;
|
|
966
|
+
chapterId: string;
|
|
967
|
+
environment: string;
|
|
968
|
+
/** Optional host marker; defaults to `SIGNUP_CONTROL_THEME_MARKER`. */
|
|
969
|
+
marker?: string;
|
|
970
|
+
}
|
|
971
|
+
/** Transformed HTML plus the exact theme and cache identity it contains. */
|
|
972
|
+
interface ActiveSignupControlHtml {
|
|
973
|
+
html: string;
|
|
974
|
+
theme: SignupControlThemeHead;
|
|
975
|
+
}
|
|
976
|
+
/**
|
|
977
|
+
* Transform trusted host HTML with the follower-local last-known-good signup
|
|
978
|
+
* theme. A missing active revision uses the documented bootstrap state; a read
|
|
979
|
+
* failure or corrupt active row fails closed instead of fetching the hub.
|
|
980
|
+
*/
|
|
981
|
+
declare function renderActiveSignupControlHtml(html: string, options: ActiveSignupControlThemeOptions): Promise<ActiveSignupControlHtml>;
|
|
982
|
+
/**
|
|
983
|
+
* Transform an HTML response and make the cache contract safe by default.
|
|
984
|
+
* `no-store` prevents a prior digest from surviving activation; hosts that own
|
|
985
|
+
* a cache may instead key it with `result.theme.metadata.cacheKey` from
|
|
986
|
+
* {@link renderActiveSignupControlHtml}.
|
|
987
|
+
*/
|
|
988
|
+
declare function withActiveSignupControlTheme(response: Response, options: ActiveSignupControlThemeOptions): Promise<Response>;
|
|
989
|
+
|
|
793
990
|
/**
|
|
794
991
|
* Build the Cloudflare `ExportedHandler` for a chapter/hub site: Clerk-JWT
|
|
795
992
|
* verification, the source-aware admin gate, the mounted @odla-ai/crm routes, the
|
|
@@ -812,4 +1009,4 @@ declare function chapterWorker(options: ChapterWorkerOptions): {
|
|
|
812
1009
|
fetch(req: Request, env: ChapterEnv): Promise<Response>;
|
|
813
1010
|
};
|
|
814
1011
|
|
|
815
|
-
export { type ChapterEnv, type ChapterWorkerOptions, type Route, type SignupControlDeliveryOptions, type WorkerContext, chapterWorker, createWorkerContext, deliverSignupControl };
|
|
1012
|
+
export { type ActiveSignupControlHtml, type ActiveSignupControlThemeOptions, type AdmissionGrantDeliveryOptions, type ChapterEnv, type ChapterWorkerOptions, type Route, type SignupControlDeliveryOptions, type WorkerContext, chapterWorker, createWorkerContext, deliverAdmissionGrants, deliverSignupControl, renderActiveSignupControlHtml, withActiveSignupControlTheme };
|