@odla-ai/chapter 0.38.1 → 0.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +14 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/dist/worker/index.cjs +27 -3
- package/dist/worker/index.cjs.map +1 -1
- package/dist/worker/index.js +27 -3
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/member.ts","../src/application-id.ts","../src/email-identity.ts","../src/schema-applications.ts","../src/schema-admission.ts","../src/schema-gifts.ts","../src/schema.ts","../src/defaults.ts","../src/group.ts","../src/auth.ts","../src/pipeline.ts","../src/copy-defaults-admin.ts","../src/copy-defaults.ts","../src/copy-resolve.ts","../src/flow-fields.ts","../src/formation.ts","../src/config-network.ts","../src/config-signup-control.ts","../src/config-member-content.ts","../src/leader.ts","../src/descriptor.ts","../src/tiers.ts","../src/member-content-validation-helpers.ts","../src/member-content-validation.ts","../src/member-content.ts","../src/member-content-canonical.ts","../src/email.ts","../src/notify.ts","../src/payments.ts","../src/admission-grants-contract.ts","../src/signup-control-canonical.ts","../src/admission-grants.ts","../src/join-continuation.ts","../src/gift-offers.ts","../src/network.ts","../src/network-contract.ts","../src/crm-sync.ts","../src/series.ts","../src/payments-stripe.ts","../src/clerk.ts","../src/clerk-roles.ts","../src/clerk-integration.ts","../src/session.ts","../src/brand.ts","../src/reconcile.ts","../src/scheduling.ts","../src/tiers-store.ts","../src/signup-control-contract.ts","../src/membership-page.ts","../src/signup-control-validate.ts","../src/signup-control-theme.ts","../src/membership-markdown.ts","../src/promotion.ts"],"sourcesContent":["// defineChapter — validate-at-import config, reusing @odla-ai/crm's defineCrm.\n// A bad config throws here (startup), never at request time.\nimport { defineCrm } from \"@odla-ai/crm\";\nimport type { CrmConfig, Crm } from \"@odla-ai/crm\";\nimport type {\n Chapter,\n ChapterConfig,\n ChapterMode,\n ResolvedOperations,\n} from \"./types\";\nimport { chapterDb } from \"./schema\";\nimport { defaultCrm } from \"./defaults\";\nimport { buildGroupSeed } from \"./group\";\nimport { resolveAuth } from \"./auth\";\nimport { resolvePipeline } from \"./pipeline\";\nimport { resolveApplication } from \"./member\";\nimport { resolveChapterCopy } from \"./copy\";\nimport { resolveLeaderFormation } from \"./formation\";\nimport { resolveNetwork } from \"./config-network\";\nimport { resolveSignupControl } from \"./config-signup-control\";\nimport { resolveMemberContent } from \"./config-member-content\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\n\nfunction isResolvedCrm(x: CrmConfig | Crm | undefined): x is Crm {\n return (\n !!x &&\n typeof x === \"object\" &&\n \"prepare\" in x &&\n typeof (x as { prepare?: unknown }).prepare === \"function\"\n );\n}\n\n/**\n * Validate a chapter/hub config and resolve its engine — the CRM, the chapter's\n * odla-db schema/rules, and the seed groups row. Throws at import on a bad\n * config (bad slug, wrong mode, missing chapter-mode prices/emails), never at\n * request time.\n */\nexport function defineChapter(config: ChapterConfig): Chapter {\n if (!config || typeof config !== \"object\") throw new Error(\"defineChapter: a config object is required\");\n const { id, name } = config;\n if (typeof id !== \"string\" || !SLUG.test(id)) {\n throw new Error(`defineChapter.id: must be a lowercase slug [a-z0-9-] (2-63 chars) — got ${JSON.stringify(id)}`);\n }\n if (typeof name !== \"string\" || name.trim() === \"\") throw new Error(\"defineChapter.name: a non-empty name is required\");\n\n const mode: ChapterMode = config.mode ?? \"chapter\";\n if (mode !== \"chapter\" && mode !== \"hub\") throw new Error(`defineChapter.mode: must be \"chapter\" or \"hub\" — got ${JSON.stringify(config.mode)}`);\n\n const crm: Crm = isResolvedCrm(config.crm) ? config.crm : defineCrm(config.crm ?? defaultCrm(mode));\n\n if (mode === \"chapter\") {\n if (!config.emails || typeof config.emails.notificationEmail !== \"string\" || config.emails.notificationEmail === \"\") {\n throw new Error(\"defineChapter.emails.notificationEmail: required in chapter mode\");\n }\n if (!config.prices || typeof config.prices.standardCents !== \"number\") {\n throw new Error(\"defineChapter.prices.standardCents: required in chapter mode\");\n }\n if (config.account === undefined) {\n throw new Error('defineChapter.account: required in chapter mode; choose \"none\", \"create\", or \"invite\" explicitly');\n }\n }\n\n const auth = resolveAuth(mode, config.auth);\n const pipeline = resolvePipeline(config.pipeline);\n const application = resolveApplication(config.application);\n const brand = { ...config.brand, wordmark: config.brand?.wordmark ?? name };\n const copy = resolveChapterCopy(config.copy);\n const network = resolveNetwork(config, crm);\n const signupControl = resolveSignupControl(config.signupControl);\n const memberContent = resolveMemberContent(config.memberContent);\n const formation = resolveLeaderFormation(config.formation, crm);\n if (signupControl && mode !== \"chapter\") {\n throw new Error(\"defineChapter.signupControl: only chapter-mode followers can receive signup control\");\n }\n if (memberContent && mode !== \"chapter\") {\n throw new Error(\"defineChapter.memberContent: only chapter-mode sites can serve member content\");\n }\n const { schema, rules } = chapterDb(\n mode, auth, network.targets.length > 0, application, Boolean(signupControl), Boolean(memberContent),\n );\n const services = config.services ?? [\"db\", \"calendar\", \"o11y\"];\n // Hub mode has no public application flow, so its inert resolved value remains\n // `none`. Chapter mode was required to make this decision above.\n const account = config.account ?? \"none\";\n if (account !== \"invite\" && account !== \"create\" && account !== \"none\") {\n throw new Error(`defineChapter.account: must be \"invite\", \"create\", or \"none\" — got \"${String(account)}\"`);\n }\n // crmFields not declared on the CRM person type are dropped by the projection at\n // runtime (the base person still lands), so a typo is invisible. Both the\n // resolved crmFields and the resolved crm are in hand here — cross-check the\n // names and fail at resolve time instead.\n if (application.crmFields.length > 0) {\n let personFields: string[] | null = null;\n try {\n personFields = Object.keys(crm.type(\"person\").fields ?? {});\n } catch {\n // No introspectable \"person\" type — leave it to the projection.\n }\n const unknown = personFields ? application.crmFields.filter((f) => !personFields.includes(f)) : [];\n if (unknown.length > 0) {\n throw new Error(\n `defineChapter.application.crmFields: ${unknown.map((f) => `\"${f}\"`).join(\", \")} not declared on the CRM \"person\" type ` +\n `(declared: ${personFields?.join(\", \")}). An undeclared field is silently dropped from the CRM projection — ` +\n `add it to your crm config's person fields, or remove it from crmFields.`,\n );\n }\n }\n const adminNotification = config.sends?.adminNotification ?? \"submit\";\n if (adminNotification !== \"submit\" && adminNotification !== \"payment\" && adminNotification !== \"never\") {\n throw new Error(\n `defineChapter.sends.adminNotification: must be \"submit\", \"payment\", or \"never\" — got \"${String(adminNotification)}\"`,\n );\n }\n const sends = { adminNotification };\n\n // Admin-operation policy. The escalation RULES are not here — they are\n // package-enforced in canChangeRole (gated on auth.superAdmins), so a site\n // cannot weaken them. These two are genuine per-site decisions.\n const onApproveCfg = config.operations?.onApprove ?? {};\n // Default promotion target: the rung directly below admin, so a custom ladder\n // gets the right answer instead of a hardcoded \"member\".\n const belowAdmin = auth.ladder[auth.ladder.length - 2] ?? auth.adminRole;\n const promoteTo = onApproveCfg.promoteTo === undefined ? belowAdmin : onApproveCfg.promoteTo;\n if (promoteTo !== false && !auth.ladder.includes(promoteTo)) {\n throw new Error(\n `defineChapter.operations.onApprove.promoteTo: \"${String(promoteTo)}\" is not in the auth ladder (${auth.ladder.join(\", \")})`,\n );\n }\n const refundCfg = config.operations?.refund ?? {};\n if (refundCfg.allowedFrom !== undefined) {\n const unknown = refundCfg.allowedFrom.filter((s) => !pipeline.stages.includes(s));\n if (unknown.length > 0) {\n throw new Error(\n `defineChapter.operations.refund.allowedFrom: ${unknown.map((s) => `\"${s}\"`).join(\", \")} not in the pipeline (${pipeline.stages.join(\", \")})`,\n );\n }\n }\n const operations: ResolvedOperations = {\n onApprove: { promoteTo, send: onApproveCfg.send === undefined ? \"onboardingInvite\" : onApproveCfg.send },\n refund: { allowedFrom: refundCfg.allowedFrom ?? null, cancelSubscription: refundCfg.cancelSubscription ?? true },\n };\n\n const chapter: Chapter = {\n config,\n id,\n name,\n mode,\n brand,\n copy,\n network,\n signupControl,\n memberContent,\n formation,\n crm,\n auth,\n pipeline,\n application,\n schema,\n rules,\n services,\n account,\n sends,\n operations,\n groupSeed: () => (mode === \"chapter\" ? buildGroupSeed(config) : null),\n };\n if (config.url !== undefined) chapter.url = config.url;\n return chapter;\n}\n","// The public member surface logic: the join config a site's join page reads (B1)\n// and the idempotent application submit (B2 validation + B3 exactly-once). Both\n// take the structural ChapterDb, so they're tested against an in-memory fake and\n// carry no runtime @odla-ai/db import. The worker builds the real db client, does\n// Clerk verification, enforces the body cap, and mounts these on chapter routes.\nimport type { Chapter, ChapterApplication, ChapterDb, ResolvedApplication } from \"./types\";\nimport { assertFieldCondition, resolveFieldStates } from \"@odla-ai/crm\";\nimport type { FieldConditions } from \"@odla-ai/crm\";\nimport { applicationIdForSubmission } from \"./application-id\";\nimport type { JoinConfigTier } from \"./tiers\";\nimport type { AdmissionGrantRow } from \"./admission-grants\";\nimport { normalizeChapterEmail } from \"./email-identity\";\n\n// The reference join form. `focus` (a json field) is always accepted.\nconst DEFAULT_REQUIRED = [\"firstName\", \"lastName\", \"email\", \"referral\", \"whoYouAre\", \"message\"];\nconst DEFAULT_OPTIONAL = [\"referralName\", \"linkedin\", \"phone\", \"state\"];\nconst SCHEMA_FIELD = /^[A-Za-z_][A-Za-z0-9_-]*$/;\n\n/** Apply defaults + validate the application config. Throws at import on bad shape. */\nexport function resolveApplication(a: ChapterApplication | undefined): ResolvedApplication {\n const required = a?.required ?? DEFAULT_REQUIRED;\n const optional = a?.optional ?? DEFAULT_OPTIONAL;\n for (const [name, arr] of [[\"required\", required], [\"optional\", optional]] as const) {\n if (!Array.isArray(arr) || !arr.every((f) => typeof f === \"string\" && f !== \"\")) {\n throw new Error(`defineChapter.application.${name}: must be an array of field-name strings`);\n }\n const unsafe = arr.find((field) => !SCHEMA_FIELD.test(field));\n if (unsafe) {\n throw new Error(`defineChapter.application.${name}: field \"${unsafe}\" must match ${SCHEMA_FIELD.source}`);\n }\n }\n const duplicate = [...required, ...optional].find((field, index, fields) => fields.indexOf(field) !== index);\n if (duplicate) {\n throw new Error(`defineChapter.application: duplicate field \"${duplicate}\" across required/optional lists`);\n }\n if (a?.profileFields !== undefined && (!Array.isArray(a.profileFields) || !a.profileFields.every((f) => typeof f === \"string\" && f !== \"\"))) {\n throw new Error(\"defineChapter.application.profileFields: must be an array of field-name strings\");\n }\n if (a?.crmFields !== undefined && (!Array.isArray(a.crmFields) || !a.crmFields.every((f) => typeof f === \"string\" && f !== \"\"))) {\n throw new Error(\"defineChapter.application.crmFields: must be an array of field-name strings\");\n }\n // Conditions are checked when the chapter is defined, so a typo fails at\n // startup rather than quietly misbehaving on a live join page. Fields that\n // fail open at runtime are the deliberate second line of defence, not this.\n const conditions = a?.conditions ?? {};\n for (const [field, declared] of Object.entries(conditions)) {\n for (const key of [\"visibleWhen\", \"requiredWhen\"] as const) {\n const expression = declared?.[key];\n if (expression === undefined) continue;\n if (typeof expression !== \"string\" || !expression.trim()) {\n throw new Error(`defineChapter.application.conditions.${field}.${key}: must be a non-empty CEL condition`);\n }\n assertFieldCondition(expression, `defineChapter.application.conditions.${field}.${key}`);\n }\n }\n return {\n required,\n optional,\n conditions,\n maxLen: a?.maxLen ?? {},\n defaultMaxLen: a?.defaultMaxLen ?? 2000,\n bodyCap: a?.bodyCap ?? 32768,\n requireDisclaimerAck: a?.requireDisclaimerAck ?? true,\n profileFields: a?.profileFields ?? [],\n crmFields: a?.crmFields ?? [],\n maxArrayLen: a?.maxArrayLen ?? 100,\n validateEmail: a?.validateEmail ?? true,\n };\n}\n\n// A permissive email shape check: one @, a dot-bearing domain, no whitespace.\n// Deliberately not RFC-exhaustive — the goal is to reject \"notanemail\" before it\n// fails the downstream Clerk create, not to adjudicate exotic-but-valid addresses.\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/** Whether a string looks like an email address (see {@link EMAIL_RE}). Exported\n * so a site building its own submit path applies the same rule chapter does. */\nexport function isValidEmail(value: unknown): boolean {\n return typeof value === \"string\" && EMAIL_RE.test(value);\n}\n\n/** Bound an array-valued field: drop non-primitive elements and cap the length,\n * so a client cannot post an unbounded array. Non-arrays pass through unchanged. */\nexport function clampArray(value: unknown, max: number): unknown {\n if (!Array.isArray(value)) return value;\n return value.filter((x) => typeof x === \"string\" || typeof x === \"number\" || typeof x === \"boolean\").slice(0, max);\n}\n\n/** Whether a submit body carries a genuine disclaimer acknowledgement. Accepts\n * the boolean an API client sends and the string a plain HTML form posts. */\nexport function hasDisclaimerAck(fields: Record<string, unknown>): boolean {\n return fields.disclaimerAck === true || fields.disclaimerAck === \"true\";\n}\n\n// Clerk carries these as first-class user fields, so repeating them in\n// public_metadata would be duplicated state that can drift.\nconst IDENTITY_FIELDS = new Set([\"email\", \"firstName\", \"lastName\"]);\n\n/**\n * The applicant profile written to the Clerk account's backend-only\n * `private_metadata.profile`. Projects each configured non-identity field, plus\n * `focus` (clamped), but ONLY those in `application.profileFields`. Derived\n * from config, so a site's own field names project without this package knowing\n * them. Pure; returns `undefined` when there is nothing to write.\n */\nexport function applicantProfile(\n chapter: Chapter,\n fields: Record<string, unknown>,\n): Record<string, unknown> | undefined {\n const app = chapter.application;\n const allowed = (f: string): boolean => app.profileFields.includes(f);\n const profile: Record<string, unknown> = {};\n for (const f of [...app.required, ...app.optional]) {\n if (IDENTITY_FIELDS.has(f) || !allowed(f)) continue;\n const v = fields[f];\n if (typeof v === \"string\" && v.trim() !== \"\") profile[f] = v.trim();\n }\n if (fields.focus !== undefined && allowed(\"focus\")) profile.focus = clampArray(fields.focus, app.maxArrayLen);\n return Object.keys(profile).length > 0 ? profile : undefined;\n}\n\n/** A validated submission, or a 400-worthy validation error the route returns.\n * `disclaimerAckAt` reports what THIS request recorded — a number when consent\n * was stamped, `null` when none was supplied. It is always present so a missing\n * consent record is visible in the response rather than silently absent from a\n * row nobody reads until an audit. */\nexport type SubmitResult =\n | { ok: true; id: string; duplicate: boolean; status: string; disclaimerAckAt: number | null }\n | { ok: false; error: string };\n\n/**\n * Submit a membership application (B2 + B3). Validates the configured required\n * fields + max lengths, writes the `applications` row at the pipeline's initial\n * status, and — when the client supplies a `submissionId` — stamps it as the\n * transaction's mutationId (`join:${submissionId}`) so a double-tap can never\n * create two applications. The application id is derived from that same stable\n * input, so the duplicate response returns the first request's canonical id\n * rather than a fresh, nonexistent one. Idempotency is package-enforced.\n * `now`/`newId` are injected (deterministic in tests).\n */\nexport async function submitApplication(\n db: ChapterDb,\n chapter: Chapter,\n fields: Record<string, unknown>,\n opts: {\n submissionId?: string;\n groupId?: string;\n now: number;\n newId: () => string;\n /** Tier ids this chapter offers. A posted `tierId` outside it is refused;\n * omit to accept any (pre-tier callers). */\n tierIds?: readonly string[];\n /** Effective one-use waiver selected by the server, never by the client. */\n admissionGrant?: AdmissionGrantRow;\n /** Server-validated gift offer selected from active signed control. */\n giftOfferId?: string;\n },\n): Promise<SubmitResult> {\n const app = chapter.application;\n // Requiredness is resolved against the answers, not read off a static list,\n // so a conditionally-hidden field is not demanded and a conditionally-\n // required one cannot be skipped by posting straight to this route. The\n // renderer calls the same resolver, so the form and the validator cannot\n // disagree. With no conditions declared this is exactly the old static loop.\n const fieldStates = resolveFieldStates(app.conditions ?? {}, fields, app.required);\n for (const [f, state] of Object.entries(fieldStates)) {\n if (!state.required) continue;\n const v = fields[f];\n if (typeof v !== \"string\" || v.trim() === \"\") return { ok: false, error: `${f} is required` };\n }\n for (const f of [...app.required, ...app.optional]) {\n const v = fields[f];\n const cap = app.maxLen[f] ?? app.defaultMaxLen;\n if (typeof v === \"string\" && v.length > cap) return { ok: false, error: `${f} exceeds ${cap} characters` };\n }\n // A malformed email can only fail the downstream Clerk create; reject it here\n // as a clean 400. A valid application always has a valid email, so no genuine\n // submission is newly rejected.\n if (app.validateEmail && typeof fields.email === \"string\" && !isValidEmail(fields.email.trim())) {\n return { ok: false, error: \"email must be a valid email address\" };\n }\n\n const acked = hasDisclaimerAck(fields);\n if (app.requireDisclaimerAck && !acked) {\n return { ok: false, error: \"disclaimerAck is required\" };\n }\n\n const id = opts.submissionId\n ? await applicationIdForSubmission(opts.submissionId)\n : opts.newId();\n const row: Record<string, unknown> = { id, status: chapter.pipeline.initial, createdAt: opts.now };\n for (const f of [...app.required, ...app.optional]) {\n // A field the conditions hid was never asked, so a value for it is stale\n // or forged. Storing it would answer a question on the applicant's behalf.\n if (fieldStates[f]?.visible === false) continue;\n if (typeof fields[f] === \"string\") row[f] = (fields[f] as string).trim();\n }\n if (fields.focus !== undefined) row.focus = clampArray(fields.focus, app.maxArrayLen);\n if (opts.groupId) row.groupId = opts.groupId;\n if (typeof fields.email === \"string\" && isValidEmail(fields.email.trim())) {\n row.emailNormalized = normalizeChapterEmail(fields.email);\n }\n if (opts.admissionGrant?.decision === \"waive_interview\") {\n row.admissionGrantId = opts.admissionGrant.id;\n row.admissionSource = opts.admissionGrant.sourceScope;\n row.interviewWaivedAt = opts.now;\n }\n if (opts.giftOfferId) row.giftOfferId = opts.giftOfferId;\n // A tier decides what this member is charged, so the posted id is checked\n // against what the chapter actually offers rather than trusted. An unknown\n // id is refused instead of silently dropped: dropping it would bill the\n // applicant whatever the fallback tier costs.\n if (typeof fields.tierId === \"string\" && fields.tierId) {\n if (opts.tierIds && !opts.tierIds.includes(fields.tierId)) {\n return { ok: false, error: \"tierId is not an offered tier\" };\n }\n row.tierId = fields.tierId;\n }\n // The disclaimer acknowledgement is a compliance record, so it is stamped from\n // the server clock on a genuine ack and left absent otherwise — a client-supplied\n // timestamp would be forgeable, and a row that always carries one would record\n // consent nobody gave.\n if (acked) row.disclaimerAckAt = opts.now;\n\n const ops: Parameters<ChapterDb[\"transact\"]>[0] = [\n { t: \"update\", ns: \"applications\", id, attrs: row },\n ];\n if (opts.admissionGrant?.decision === \"waive_interview\") {\n ops.push({ t: \"update\", ns: \"admissionGrants\", id: opts.admissionGrant.id, attrs: {\n consumedAt: opts.now,\n consumedApplicationId: id,\n } });\n }\n const { duplicate } = await db.transact(\n ops,\n opts.submissionId ? { mutationId: `join:${opts.submissionId}` } : undefined,\n );\n return { ok: true, id, duplicate, status: chapter.pipeline.initial, disclaimerAckAt: acked ? opts.now : null };\n}\n\n/** The `groups`-row fields the join config exposes. */\nexport interface JoinConfigGroup {\n id: string;\n name: string;\n standardPriceCents?: number;\n foundingDiscountCents?: number;\n disclaimerText?: string;\n refundPolicyText?: string;\n trustCopy?: string;\n commitmentText?: string;\n normsText?: string;\n}\n\n/**\n * The public join config (B1) a site's join page reads: copy + prices from the\n * group row plus `paymentsReady`. When payments aren't wired the join flow drops\n * the payment step (C2) — the worker computes `paymentsReady` from the group's\n * Stripe keys + vault secret. Pure.\n *\n * `tiers` carries the offerable membership tiers. It is additive: the legacy\n * `standardPriceCents`/`foundingDiscountCents` fields still describe the first\n * tier, so a join page written before tiers keeps rendering unchanged. A free\n * tier appears here with `free: true` even when Stripe is unconfigured, because\n * nothing needs charging for it.\n */\nexport function joinConfig(\n group: JoinConfigGroup,\n paymentsReady: boolean,\n tiers: readonly JoinConfigTier[] = [],\n conditions: Readonly<Record<string, FieldConditions>> = {},\n): Record<string, unknown> {\n return {\n id: group.id,\n name: group.name,\n standardPriceCents: group.standardPriceCents ?? 0,\n foundingDiscountCents: group.foundingDiscountCents ?? 0,\n tiers: [...tiers],\n // The browser evaluates the same conditions the server enforces.\n conditions,\n disclaimerText: group.disclaimerText ?? \"\",\n refundPolicyText: group.refundPolicyText ?? \"\",\n trustCopy: group.trustCopy ?? \"\",\n commitmentText: group.commitmentText ?? \"\",\n normsText: group.normsText ?? \"\",\n paymentsReady,\n };\n}\n","// Application creates use a caller-stable submission id as their database\n// mutation id. The entity id must be derived from that same stable input: if a\n// committed request is retried, the database correctly skips the new ops and\n// Chapter must still return the id of the row written by the first request.\n\nconst APPLICATION_ID_DOMAIN = \"odla-ai/chapter/application/v1:\";\n\n/**\n * Derive the UUID-shaped capability for an idempotent application submission.\n * SHA-256 prevents a caller from choosing a submission id that overwrites a\n * known application id; UUIDv8 bits preserve the identifier shape consumers\n * already expect.\n */\nexport async function applicationIdForSubmission(submissionId: string): Promise<string> {\n const input = new TextEncoder().encode(`${APPLICATION_ID_DOMAIN}${submissionId}`);\n const bytes = new Uint8Array(await crypto.subtle.digest(\"SHA-256\", input)).slice(0, 16);\n bytes[6] = (bytes[6]! & 0x0f) | 0x80;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","/**\n * Normalize an email address for Chapter identity lookups.\n *\n * Chapter treats the address literally: surrounding whitespace and ASCII case\n * are insignificant, but the local part is otherwise preserved. In\n * particular, provider-specific aliases are never collapsed, so\n * `foo+bar@gmail.com` and `foo@gmail.com` remain distinct applicants,\n * admission decisions, purchasers, and beneficiaries.\n */\nexport function normalizeChapterEmail(email: string): string {\n return email.trim().toLowerCase();\n}\n","import type { Attr, AttrType, Entity, ResolvedApplication } from \"./types\";\n\nconst attr = (type: AttrType, flags: { unique?: boolean; indexed?: boolean; optional?: boolean } = {}): Attr => ({\n type, unique: flags.unique ?? false, indexed: flags.indexed ?? false, optional: flags.optional ?? false,\n});\n\nconst APPLICATION_INPUT_FIELDS = new Set([\n \"firstName\", \"lastName\", \"email\", \"referral\", \"referralName\", \"whoYouAre\",\n \"focus\", \"linkedin\", \"message\", \"phone\", \"state\",\n]);\n\nconst applicationAttrs: Record<string, Attr> = {\n id: attr(\"string\", { unique: true, indexed: true }), firstName: attr(\"string\"), lastName: attr(\"string\"),\n email: attr(\"string\", { indexed: true }), referral: attr(\"string\"), referralName: attr(\"string\", { optional: true }),\n whoYouAre: attr(\"string\"), focus: attr(\"json\"), linkedin: attr(\"string\", { optional: true }), message: attr(\"string\"),\n status: attr(\"string\", { indexed: true }), createdAt: attr(\"number\", { indexed: true }),\n meetingAt: attr(\"number\", { indexed: true, optional: true }), meetingLink: attr(\"string\", { optional: true }),\n clerkUserId: attr(\"string\", { indexed: true, optional: true }), clerkPrivateMetadataSyncedAt: attr(\"number\", { optional: true }),\n phone: attr(\"string\", { optional: true }), state: attr(\"string\", { optional: true }),\n groupId: attr(\"string\", { indexed: true, optional: true }), tierId: attr(\"string\", { indexed: true, optional: true }),\n stripeCustomerId: attr(\"string\", { indexed: true, optional: true }),\n stripeSubscriptionId: attr(\"string\", { indexed: true, optional: true }), renewalAt: attr(\"number\", { optional: true }),\n disclaimerAckAt: attr(\"number\", { optional: true }), refundPolicyAckAt: attr(\"number\", { optional: true }),\n prepEmailSentAt: attr(\"number\", { optional: true }), canceled: attr(\"boolean\", { optional: true }),\n emailNormalized: attr(\"string\", { indexed: true, optional: true }),\n admissionGrantId: attr(\"string\", { unique: true, indexed: true, optional: true }),\n admissionSource: attr(\"string\", { indexed: true, optional: true }), interviewWaivedAt: attr(\"number\", { optional: true }),\n giftOfferId: attr(\"string\", { optional: true, indexed: true }),\n giftIntentId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n giftClaimId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n giftOrderId: attr(\"string\", { optional: true, indexed: true }), giftPaidAt: attr(\"number\", { optional: true, indexed: true }),\n giftRevokedAt: attr(\"number\", { optional: true, indexed: true }),\n giftCheckoutStartedAt: attr(\"number\", { optional: true, indexed: true }),\n};\n\n/** Resolve the site-configurable application inputs without exposing operational fields. */\nexport function applicationsFor(application: ResolvedApplication): Entity {\n const attrs: Record<string, Attr> = {};\n for (const [name, spec] of Object.entries(applicationAttrs)) {\n attrs[name] = { ...spec, optional: APPLICATION_INPUT_FIELDS.has(name) ? true : spec.optional };\n }\n const apply = (field: string, optional: boolean): void => {\n const existing = Object.hasOwn(attrs, field) ? attrs[field] : undefined;\n if (existing && !APPLICATION_INPUT_FIELDS.has(field)) throw new Error(`defineChapter.application: field \"${field}\" is reserved by the applications schema`);\n if (existing && existing.type !== \"string\") throw new Error(`defineChapter.application: field \"${field}\" is not a configurable string field`);\n Object.defineProperty(attrs, field, {\n value: existing ? { ...existing, optional } : attr(\"string\", { optional }),\n enumerable: true, configurable: true, writable: true,\n });\n };\n for (const field of application.required) apply(field, false);\n for (const field of application.optional) apply(field, true);\n return { attrs };\n}\n","import type { Attr, AttrType, Entity } from \"./types\";\n\nconst attr = (type: AttrType, flags: { unique?: boolean; indexed?: boolean; optional?: boolean } = {}): Attr => ({\n type,\n unique: flags.unique ?? false,\n indexed: flags.indexed ?? false,\n optional: flags.optional ?? false,\n});\nconst id = (): Attr => attr(\"string\", { unique: true, indexed: true });\n\n/** Operational Parent and Chapter admission decisions, never publicly readable. */\nexport const admissionGrantsEntity: Entity = {\n attrs: {\n id: id(),\n sourceGrantId: attr(\"string\", { indexed: true }),\n sourceScope: attr(\"string\", { indexed: true }),\n sourceId: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n email: attr(\"string\"),\n emailNormalized: attr(\"string\", { indexed: true }),\n decision: attr(\"string\", { indexed: true }),\n note: attr(\"string\", { optional: true }),\n active: attr(\"boolean\", { indexed: true }),\n sourceRevision: attr(\"number\", { optional: true, indexed: true }),\n createdAt: attr(\"number\", { indexed: true }),\n createdBy: attr(\"string\", { optional: true, indexed: true }),\n updatedAt: attr(\"number\", { optional: true, indexed: true }),\n updatedBy: attr(\"string\", { optional: true, indexed: true }),\n expiresAt: attr(\"number\", { optional: true, indexed: true }),\n revokedAt: attr(\"number\", { optional: true, indexed: true }),\n revokedBy: attr(\"string\", { optional: true, indexed: true }),\n consumedAt: attr(\"number\", { optional: true, indexed: true }),\n consumedApplicationId: attr(\"string\", { optional: true, indexed: true }),\n },\n};\n\n/** Immutable acknowledgements for signed Parent admission documents. */\nexport const admissionGrantRevisionsEntity: Entity = {\n attrs: {\n id: id(),\n sourceId: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }),\n revision: attr(\"number\", { indexed: true }),\n digest: attr(\"string\", { indexed: true }),\n active: attr(\"boolean\", { indexed: true }),\n receivedAt: attr(\"number\", { indexed: true }),\n },\n};\n","import type { Attr, AttrType, Entity } from \"./types\";\n\nconst attr = (type: AttrType, flags: { unique?: boolean; indexed?: boolean; optional?: boolean } = {}): Attr => ({\n type, unique: flags.unique ?? false, indexed: flags.indexed ?? false, optional: flags.optional ?? false,\n});\nconst id = (): Attr => attr(\"string\", { unique: true, indexed: true });\n\n/** Pre-payment gift checkout state. It holds only a code hash, never plaintext. */\nexport const giftPurchaseIntentsEntity: Entity = { attrs: {\n id: id(), chapterId: attr(\"string\", { indexed: true }), environment: attr(\"string\", { indexed: true }),\n purchaserType: attr(\"string\", { indexed: true }), purchaserApplicationId: attr(\"string\", { optional: true, indexed: true }),\n purchaserUserId: attr(\"string\", { optional: true, indexed: true }), purchaserEmailNormalized: attr(\"string\", { indexed: true }),\n offerId: attr(\"string\", { indexed: true }), offerSnapshot: attr(\"json\"), status: attr(\"string\", { indexed: true }),\n codeHash: attr(\"string\", { indexed: true }), codeVersion: attr(\"number\"), codeIssuedAt: attr(\"number\"),\n providerObjectId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n providerCustomerId: attr(\"string\", { optional: true, indexed: true }), checkoutStartedAt: attr(\"number\", { optional: true }),\n paidAt: attr(\"number\", { optional: true, indexed: true }), claimId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n createdAt: attr(\"number\", { indexed: true }), updatedAt: attr(\"number\", { indexed: true }),\n} };\n\n/** Immutable provider-authorized gift purchase evidence. */\nexport const giftOrdersEntity: Entity = { attrs: {\n id: id(), intentId: attr(\"string\", { unique: true, indexed: true }), chapterId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }), offerId: attr(\"string\", { indexed: true }), offerSnapshot: attr(\"json\"),\n purchaserType: attr(\"string\", { indexed: true }), purchaserApplicationId: attr(\"string\", { optional: true, indexed: true }),\n purchaserUserId: attr(\"string\", { optional: true, indexed: true }), purchaserEmailNormalized: attr(\"string\", { indexed: true }),\n providerEventId: attr(\"string\", { unique: true, indexed: true }), providerObjectId: attr(\"string\", { indexed: true }),\n amountCents: attr(\"number\"), currency: attr(\"string\"), billingMode: attr(\"string\"), createdAt: attr(\"number\", { indexed: true }),\n} };\n\n/** Single-use beneficiary bearer claim. Buyer list routes never return its hash. */\nexport const giftClaimsEntity: Entity = { attrs: {\n id: id(), orderId: attr(\"string\", { unique: true, indexed: true }), intentId: attr(\"string\", { unique: true, indexed: true }),\n chapterId: attr(\"string\", { indexed: true }), offerId: attr(\"string\", { indexed: true }), target: attr(\"json\"),\n purchaserApplicationId: attr(\"string\", { optional: true, indexed: true }), purchaserUserId: attr(\"string\", { optional: true, indexed: true }),\n purchaserEmailNormalized: attr(\"string\", { indexed: true }), codeHash: attr(\"string\", { unique: true, indexed: true }),\n codeVersion: attr(\"number\"), rotationCount: attr(\"number\"), codeIssuedAt: attr(\"number\"), codeExpiresAt: attr(\"number\", { indexed: true }),\n attemptCount: attr(\"number\"), attemptWindowStartedAt: attr(\"number\"), status: attr(\"string\", { indexed: true }),\n redeemedAt: attr(\"number\", { optional: true, indexed: true }), beneficiaryEmailNormalized: attr(\"string\", { optional: true, indexed: true }),\n beneficiaryUserId: attr(\"string\", { optional: true, indexed: true }), applicationId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n entitlementId: attr(\"string\", { optional: true, unique: true, indexed: true }), rotatedAt: attr(\"number\", { optional: true }),\n revokedAt: attr(\"number\", { optional: true, indexed: true }), revokedReason: attr(\"string\", { optional: true }), createdAt: attr(\"number\", { indexed: true }),\n} };\n\n/** Non-membership beneficiary entitlements created by redeemed gift claims. */\nexport const giftEntitlementsEntity: Entity = { attrs: {\n id: id(), claimId: attr(\"string\", { unique: true, indexed: true }), orderId: attr(\"string\", { indexed: true }),\n chapterId: attr(\"string\", { indexed: true }), entitlementKey: attr(\"string\", { indexed: true }),\n beneficiaryEmailNormalized: attr(\"string\", { indexed: true }), beneficiaryUserId: attr(\"string\", { optional: true, indexed: true }),\n active: attr(\"boolean\", { indexed: true }), createdAt: attr(\"number\", { indexed: true }), revokedAt: attr(\"number\", { optional: true }),\n} };\n\n/** Coarse requester buckets that bound public redemption attempts. */\nexport const giftRedemptionAttemptsEntity: Entity = { attrs: {\n id: id(), chapterId: attr(\"string\", { indexed: true }), bucket: attr(\"string\", { indexed: true }),\n attemptCount: attr(\"number\"), windowStartedAt: attr(\"number\", { indexed: true }), updatedAt: attr(\"number\"),\n} };\n","// The chapter's own odla-db namespaces: the operational membership tables\n// (applications, groups, meetings, emailLog) plus the auth tables the resolved\n// auth policy selects — the `admins` allowlist (source \"table\") and/or the\n// read-only `superAdmins` tier. All deny-all. The `crm_*` namespaces are\n// contributed separately by @odla-ai/crm's integration and merged by the CLI.\nimport type {\n Attr,\n AttrType,\n DbRules,\n DbSchema,\n Entity,\n ChapterMode,\n ResolvedApplication,\n ResolvedAuth,\n} from \"./types\";\nimport { resolveApplication } from \"./member\";\nimport { applicationsFor } from \"./schema-applications\";\nimport { admissionGrantRevisionsEntity, admissionGrantsEntity } from \"./schema-admission\";\nimport {\n giftClaimsEntity, giftEntitlementsEntity, giftOrdersEntity,\n giftPurchaseIntentsEntity, giftRedemptionAttemptsEntity,\n} from \"./schema-gifts\";\n\nfunction attr(type: AttrType, flags: { unique?: boolean; indexed?: boolean; optional?: boolean } = {}): Attr {\n return {\n type,\n unique: flags.unique ?? false,\n indexed: flags.indexed ?? false,\n optional: flags.optional ?? false,\n };\n}\nconst id = (): Attr => attr(\"string\", { unique: true, indexed: true });\n\n// The allowlist that gates admin access in BOTH modes. Studio-write-only:\n// deny-all, and no worker route ever writes it. Creation time is odla-db's\n// built-in $createdAt. One row per admin, keyed by lowercased email.\nconst admins: Entity = {\n attrs: {\n id: id(),\n email: attr(\"string\", { unique: true, indexed: true }),\n name: attr(\"string\", { optional: true }),\n note: attr(\"string\", { optional: true }),\n },\n};\n\n// The super-admin tier: the ONLY tier that may create or modify admins. A\n// separate, app-READ-ONLY entity — deny-all like every namespace AND no worker\n// route ever writes it, so membership can only be set in the odla Studio data\n// browser, never from the app or an injected page script. One row per\n// super-admin, keyed by lowercased email.\nconst superAdmins: Entity = {\n attrs: {\n id: id(),\n email: attr(\"string\", { unique: true, indexed: true }),\n note: attr(\"string\", { optional: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Leader-private annotations on records that remain authoritative in a\n// follower CRM. `recordKey` is the stable target/type/id tuple used for bounded\n// reads; notes never cross the federation edge or mutate the follower.\nconst networkNotes: Entity = {\n attrs: {\n id: id(),\n recordKey: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n recordType: attr(\"string\", { indexed: true }),\n recordId: attr(\"string\", { indexed: true }),\n body: attr(\"string\"),\n authorId: attr(\"string\", { indexed: true }),\n authorEmail: attr(\"string\", { optional: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Immutable signup-control revisions. Exactly one row is active; older rows are\n// retained for audit/rollback while applicant traffic reads local state only.\nconst signupControls: Entity = {\n attrs: {\n id: id(),\n sourceId: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }),\n revision: attr(\"number\", { indexed: true }),\n digest: attr(\"string\", { indexed: true }),\n document: attr(\"json\"),\n active: attr(\"boolean\", { indexed: true }),\n receivedAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Immutable Parent member-content revisions. Exactly one row is active per\n// environment; Chapter-owned content lives in a separate singleton below so a\n// replay or replacement from the Parent cannot overwrite local authority.\nconst memberContentControls: Entity = {\n attrs: {\n id: id(),\n sourceId: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }),\n revision: attr(\"number\", { indexed: true }),\n digest: attr(\"string\", { indexed: true }),\n document: attr(\"json\"),\n active: attr(\"boolean\", { indexed: true }),\n receivedAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// One complete Chapter-owned authoring layer per environment. Admin writes are\n// revision-guarded and never share a row with inherited Parent content.\nconst memberContentLocal: Entity = {\n attrs: {\n id: id(),\n chapterId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }),\n revision: attr(\"number\", { indexed: true }),\n document: attr(\"json\"),\n updatedAt: attr(\"number\", { indexed: true }),\n updatedBy: attr(\"string\", { optional: true }),\n },\n};\n\n// Per-group settings — prices, policy copy, email templates, scheduling — never\n// in code. Seeded once from the defineChapter config (see group.ts).\nconst groups: Entity = {\n attrs: {\n id: id(),\n name: attr(\"string\"),\n standardPriceCents: attr(\"number\"),\n foundingDiscountCents: attr(\"number\"),\n stripePriceId: attr(\"string\", { optional: true }),\n stripePublishableKey: attr(\"string\", { optional: true }),\n notificationEmail: attr(\"string\"),\n replyTo: attr(\"string\"),\n debugEmail: attr(\"string\", { optional: true }),\n calendarLink: attr(\"string\", { optional: true }),\n disclaimerText: attr(\"string\"),\n refundPolicyText: attr(\"string\"),\n trustCopy: attr(\"string\"),\n commitmentText: attr(\"string\", { optional: true }),\n normsText: attr(\"string\", { optional: true }),\n emailTemplates: attr(\"json\"),\n schedulingJson: attr(\"json\", { optional: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// One row per membership tier a group offers. The price lives here rather than\n// on the group so a chapter can offer several, and so a free tier (priceCents\n// 0, no stripePriceId) is expressible at all. Deny-all like every namespace:\n// tiers are set in Studio or seeded from the chapter config, never written by a\n// join-flow route.\nconst tiers: Entity = {\n attrs: {\n id: id(),\n groupId: attr(\"string\", { indexed: true }),\n name: attr(\"string\"),\n priceCents: attr(\"number\"),\n stripePriceId: attr(\"string\", { optional: true }),\n blurb: attr(\"string\", { optional: true }),\n sortOrder: attr(\"number\", { indexed: true }),\n active: attr(\"boolean\", { indexed: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Intro-call meetings: the source of truth for scheduling; Google Calendar is a\n// projection. Drift fields record when Google disagrees with us.\nconst meetings: Entity = {\n attrs: {\n id: id(),\n applicationId: attr(\"string\", { indexed: true }),\n groupId: attr(\"string\", { indexed: true }),\n startAt: attr(\"number\", { indexed: true }),\n endAt: attr(\"number\"),\n timezone: attr(\"string\"),\n status: attr(\"string\", { indexed: true }),\n googleEventId: attr(\"string\", { indexed: true, optional: true }),\n meetUrl: attr(\"string\", { optional: true }),\n htmlLink: attr(\"string\", { optional: true }),\n drift: attr(\"string\", { indexed: true, optional: true }),\n driftGoogleStartAt: attr(\"number\", { optional: true }),\n driftDetectedAt: attr(\"number\", { optional: true }),\n adoptedFromGoogleAt: attr(\"number\", { optional: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Audit of every transactional send.\nconst emailLog: Entity = {\n attrs: {\n id: id(),\n groupId: attr(\"string\", { indexed: true }),\n applicationId: attr(\"string\", { indexed: true, optional: true }),\n to: attr(\"string\", { indexed: true }),\n template: attr(\"string\", { indexed: true }),\n subject: attr(\"string\"),\n body: attr(\"string\", { optional: true }),\n transport: attr(\"string\"),\n messageId: attr(\"string\", { optional: true }),\n redirected: attr(\"boolean\", { optional: true }),\n dedupeKey: attr(\"string\", { indexed: true, optional: true }),\n error: attr(\"string\", { optional: true }),\n sentAt: attr(\"number\", { indexed: true }),\n },\n};\n\n/** The chapter's own schema + deny-all rules for a mode + auth policy.\n *\n * In chapter mode, the optional {@link ResolvedApplication} supplies the exact\n * required/optional application string attrs. Omit it for the reference form.\n * Built-in attrs retain their types/indexes; site-defined fields become string\n * attrs, while package-owned operational attrs cannot be repurposed as inputs.\n *\n * Operational tables (`applications`/`groups`/`meetings`/`emailLog`) are added in\n * `chapter` mode only. The auth tables follow {@link ResolvedAuth}: `source:\n * \"table\"` adds the `admins` allowlist (hub/BNF); `superAdmins` adds the\n * read-only super-admin tier (default on for the `\"claim\"` ladder). A `\"claim\"`\n * chapter therefore emits the reference namespace set — `applications`,\n * `groups`, `meetings`, `emailLog`, `superAdmins` — with no `admins` table. */\nexport function chapterDb(\n mode: ChapterMode,\n auth: ResolvedAuth,\n includeNetworkNotes = false,\n application: ResolvedApplication = resolveApplication(undefined),\n includeSignupControl = false,\n includeMemberContent = false,\n): { schema: DbSchema; rules: DbRules } {\n const entities: Record<string, Entity> = {};\n if (mode === \"chapter\") {\n entities.applications = applicationsFor(application);\n entities.groups = groups;\n entities.tiers = tiers;\n entities.meetings = meetings;\n entities.emailLog = emailLog;\n entities.admissionGrants = admissionGrantsEntity;\n entities.admissionGrantRevisions = admissionGrantRevisionsEntity;\n entities.giftPurchaseIntents = giftPurchaseIntentsEntity;\n entities.giftOrders = giftOrdersEntity;\n entities.giftClaims = giftClaimsEntity;\n entities.giftEntitlements = giftEntitlementsEntity;\n entities.giftRedemptionAttempts = giftRedemptionAttemptsEntity;\n if (includeSignupControl) entities.signupControls = signupControls;\n if (includeMemberContent) {\n entities.memberContentControls = memberContentControls;\n entities.memberContentLocal = memberContentLocal;\n }\n }\n if (auth.source === \"table\") entities.admins = admins;\n if (auth.superAdmins) entities.superAdmins = superAdmins;\n if (includeNetworkNotes) entities.networkNotes = networkNotes;\n const schema: DbSchema = { entities, links: {} };\n const rules: DbRules = {};\n for (const ns of Object.keys(entities)) {\n rules[ns] = { view: \"false\", create: \"false\", update: \"false\", delete: \"false\" };\n }\n return { schema, rules };\n}\n","// Per-mode default CRM configs. Consumers pass their own via defineChapter's\n// `crm`; these are sensible starting points. Both modes share the canonical\n// people + businesses graph, while `chapter` additionally feeds the person\n// pipeline from applications through the operational package routes.\nimport type { CrmConfig } from \"@odla-ai/crm\";\nimport type { ChapterMode } from \"./types\";\n\nconst TEMPLATES: CrmConfig[\"templates\"] = {\n personal: {\n class: \"transactional\",\n vars: [\"firstName\", \"subject\", \"body\"],\n defaults: { subject: \"{{subject}}\", text: \"{{body}}\" },\n },\n announcement: {\n class: \"marketing\",\n vars: [\"firstName\", \"subject\", \"body\", \"unsubscribeUrl\"],\n defaults: { subject: \"{{subject}}\", text: \"{{body}}\\n\\n{{unsubscribeUrl}}\" },\n },\n};\n\nfunction personType(): NonNullable<CrmConfig[\"types\"]>[string] {\n return {\n label: \"Person\",\n labelPlural: \"People\",\n nameField: \"name\",\n emailField: \"email\",\n fields: {\n name: { type: \"string\", label: \"Name\", required: true },\n email: { type: \"email\", label: \"Email\" },\n firstName: { type: \"string\", label: \"First name\" },\n lastName: { type: \"string\", label: \"Last name\" },\n phone: { type: \"string\", label: \"Phone\" },\n state: { type: \"string\", label: \"State\", slot: \"s1\" },\n whoYouAre: { type: \"string\", label: \"Who they are\", slot: \"s2\" },\n referral: { type: \"string\", label: \"Referral source\", slot: \"s3\" },\n linkedin: { type: \"string\", label: \"LinkedIn\" },\n focus: { type: \"json\", label: \"Focus areas\" },\n message: { type: \"string\", label: \"Intro message\" },\n },\n pipeline: {\n stages: [\n { id: \"submitted\", label: \"Submitted\" },\n { id: \"paid_pending_vetting\", label: \"Paid, pending vetting\" },\n { id: \"call_scheduled\", label: \"Call scheduled\" },\n { id: \"interviewed\", label: \"Interviewed\" },\n { id: \"approved\", label: \"Approved\" },\n { id: \"declined\", label: \"Declined\" },\n { id: \"refunded\", label: \"Refunded\" },\n ],\n },\n facets: { identity: true, email: true, rank: \"manual\" },\n };\n}\n\nfunction companyType(): NonNullable<CrmConfig[\"types\"]>[string] {\n return {\n label: \"Business\",\n labelPlural: \"Businesses\",\n nameField: \"name\",\n fields: {\n name: { type: \"string\", label: \"Name\", required: true },\n domain: { type: \"string\", label: \"Domain / website\", slot: \"s1\" },\n industry: { type: \"string\", label: \"Industry\", slot: \"s2\" },\n location: { type: \"string\", label: \"Location\", slot: \"s3\" },\n chapter: { type: \"string\", label: \"Chapter\", slot: \"s4\" },\n linkedin: { type: \"string\", label: \"LinkedIn\" },\n notes: { type: \"string\", label: \"Notes\" },\n },\n facets: { rank: \"manual\" },\n };\n}\n\n/** The default shared CRM graph: people (with the application/member pipeline)\n * plus businesses and the `works_at` relation, in both modes. */\nexport function defaultCrm(_mode: ChapterMode): CrmConfig {\n return {\n types: { person: personType(), company: companyType() },\n relations: { works_at: { from: \"person\", to: \"company\", label: \"works at\", reverseLabel: \"team\" } },\n templates: TEMPLATES,\n };\n}\n","// Build the seed `groups` row from a defineChapter config. This is the whole\n// per-chapter payload the worker reads at runtime (prices/policy/emails/\n// scheduling), so nothing brand-specific is hardcoded in the worker. createdAt\n// is stamped by the integration/seed layer, not here.\nimport type { ChapterConfig, ChapterScheduling } from \"./types\";\n\nconst DEFAULT_SCHEDULING: Required<Omit<ChapterScheduling, \"summaryTemplate\">> = {\n slotMinutes: 45,\n days: [1, 2, 3, 4, 5],\n startHour: 9,\n endHour: 17,\n timezone: \"America/Los_Angeles\",\n minNoticeHours: 24,\n windowDays: 14,\n};\n\nfunction defaultEmailTemplates(name: string): Record<string, { subject: string; text: string }> {\n const sign = `\\n\\nWarmly,\\n${name}`;\n return {\n adminNotification: {\n subject: `New application: {{firstName}} {{lastName}}`,\n text: `A new application came in for ${name}.\\n\\nName: {{firstName}} {{lastName}}\\nEmail: {{email}}`,\n },\n paymentConfirmation: {\n subject: `Welcome to ${name}`,\n text: `Hi {{firstName}},\\n\\nYour membership payment is confirmed. We'll be in touch to schedule your intro call.${sign}`,\n },\n prepEmail: {\n subject: `Your ${name} intro call`,\n text: `Hi {{firstName}},\\n\\nLooking forward to our call at {{meetingTime}}. {{meetingLink}}${sign}`,\n },\n onboardingInvite: {\n subject: `You're in, ${name}`,\n text: `Hi {{firstName}},\\n\\nWelcome to ${name}. Your member area is here: {{membersUrl}}${sign}`,\n },\n };\n}\n\n/** The `groups` row (attrs) for `chapter` mode. Missing config falls back to\n * empty copy / defaults, so a minimal config still provisions cleanly. */\nexport function buildGroupSeed(config: ChapterConfig): Record<string, unknown> {\n const prices = config.prices;\n const emails = config.emails;\n const policy = config.policy ?? {};\n const scheduling = {\n ...DEFAULT_SCHEDULING,\n ...(config.scheduling ?? {}),\n summaryTemplate:\n config.scheduling?.summaryTemplate ?? `${config.name}: introduction call with {{firstName}} {{lastName}}`,\n };\n const row: Record<string, unknown> = {\n id: config.id,\n name: config.name,\n standardPriceCents: prices?.standardCents ?? 0,\n foundingDiscountCents: prices?.foundingDiscountCents ?? 0,\n notificationEmail: emails?.notificationEmail ?? \"\",\n replyTo: emails?.replyTo ?? emails?.notificationEmail ?? \"\",\n disclaimerText: policy.disclaimerText ?? \"\",\n refundPolicyText: policy.refundPolicyText ?? \"\",\n trustCopy: policy.trustCopy ?? \"\",\n emailTemplates: emails?.templates ?? defaultEmailTemplates(config.name),\n schedulingJson: scheduling,\n };\n if (emails?.debugEmail) row.debugEmail = emails.debugEmail;\n if (policy.commitmentText) row.commitmentText = policy.commitmentText;\n if (policy.normsText) row.normsText = policy.normsText;\n return row;\n}\n","// Identity + authorization for a chapter/hub site — the pieces every membership\n// site needs and none should re-derive: a resolved role policy, role resolution\n// from a JWT claim, the privilege-escalation guard, and a tenant-vault read.\n// Everything here is pure or structural (no runtime @odla-ai/db import), so it is\n// trivially testable and the worker stays the only thing that talks to odla-db.\nimport type { ChapterAuth, ChapterMode, ResolvedAuth } from \"./types\";\n\n/**\n * Apply defaults + validate the auth config into a {@link ResolvedAuth}. Defaults\n * by mode: `chapter` → the `provisional/member/admin` claim ladder with the\n * `superAdmins` tier; `hub` → the `admins` allowlist table with no super tier.\n * Throws at import on a bad policy.\n */\nexport function resolveAuth(mode: ChapterMode, auth: ChapterAuth | undefined): ResolvedAuth {\n const a = auth ?? {};\n const source = a.source ?? (mode === \"hub\" ? \"table\" : \"claim\");\n if (source !== \"claim\" && source !== \"table\") {\n throw new Error(`defineChapter.auth.source: must be \"claim\" or \"table\" — got ${JSON.stringify(a.source)}`);\n }\n const claim = a.claim ?? \"role\";\n if (typeof claim !== \"string\" || claim === \"\") {\n throw new Error(\"defineChapter.auth.claim: must be a non-empty string\");\n }\n const ladder = a.ladder ?? [\"provisional\", \"member\", \"admin\"];\n if (!Array.isArray(ladder) || ladder.length === 0 || !ladder.every((r) => typeof r === \"string\" && r !== \"\")) {\n throw new Error(\"defineChapter.auth.ladder: must be a non-empty array of role strings\");\n }\n const adminRole = ladder[ladder.length - 1] as string;\n const superAdmins = a.superAdmins ?? source === \"claim\";\n return { source, claim, ladder, adminRole, superAdmins };\n}\n\n/** The role from a verified JWT payload, per the resolved policy. An unknown or\n * missing claim falls back to the lowest ladder rung (fail safe, never admin). */\nexport function roleFromClaim(payload: Record<string, unknown>, auth: ResolvedAuth): string {\n const raw = payload[auth.claim];\n return typeof raw === \"string\" && auth.ladder.includes(raw) ? raw : (auth.ladder[0] as string);\n}\n\n/** Does a role meet the admin bar (the highest ladder rung)? */\nexport function isAdminRole(role: string, auth: ResolvedAuth): boolean {\n return role === auth.adminRole;\n}\n\n/** Inputs to the role-change guard — resolved by the caller (route) from the\n * identity provider + the read-only `superAdmins` table. */\nexport interface RoleChangeContext {\n actorId: string;\n actorIsSuper: boolean;\n targetId: string;\n targetCurrentRole: string;\n targetIsSuper: boolean;\n newRole: string;\n auth: ResolvedAuth;\n}\n\n/** The result of {@link canChangeRole}: allow, or deny with the HTTP status +\n * message the route should return. */\nexport type GuardResult = { ok: true } | { ok: false; status: number; error: string };\n\n/**\n * The privilege-escalation guard — package-enforced so every site gets it and\n * none re-derives it. Denies: an out-of-ladder role; changing your own role;\n * touching a super-admin unless you are one; and (when a `superAdmins` tier\n * exists) creating or altering an admin unless you are a super-admin. Note the\n * super-admin tier itself is never writable here — it lives in the read-only\n * `superAdmins` table, set only in odla Studio.\n */\nexport function canChangeRole(ctx: RoleChangeContext): GuardResult {\n const { auth } = ctx;\n if (!auth.ladder.includes(ctx.newRole)) {\n return { ok: false, status: 400, error: `role must be one of: ${auth.ladder.join(\", \")}` };\n }\n if (ctx.actorId === ctx.targetId) {\n return { ok: false, status: 400, error: \"you cannot change your own role\" };\n }\n if (ctx.targetIsSuper && !ctx.actorIsSuper) {\n return { ok: false, status: 403, error: \"this person is a super-admin; their access is managed in odla Studio\" };\n }\n const touchesAdmin = ctx.newRole === auth.adminRole || ctx.targetCurrentRole === auth.adminRole;\n if (auth.superAdmins && touchesAdmin && !ctx.actorIsSuper) {\n return { ok: false, status: 403, error: `only super-admins can create or change an ${auth.adminRole}` };\n }\n return { ok: true };\n}\n\n/** Structural view of odla-db's tenant-vault read, so chapter takes no runtime\n * dependency on @odla-ai/db. The worker's admin client satisfies this. */\nexport interface SecretStore {\n secrets: { get(name: string): Promise<string> };\n}\n\n/**\n * Read a tenant-vault secret by name; `undefined` when it is absent or the vault\n * errors, so callers degrade gracefully (e.g. `paymentsReady: false`) rather than\n * throwing. Never logs the value.\n */\nexport async function getVaultSecret(db: SecretStore, name: string): Promise<string | undefined> {\n try {\n const value = await db.secrets.get(name);\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n } catch {\n return undefined;\n }\n}\n","// The application status pipeline — config, not code. Which statuses exist, which\n// a member can book an intro call from, and which an admin can approve from\n// differ per site; the one invariant every site wants is that status never moves\n// backwards. All of this is pure + tested here; the worker enforces it on every\n// status write, and the CRM record.stage mirrors application.status (never the\n// reverse). Defaults reproduce the proven membership pipeline exactly.\nimport type { ChapterPipeline, ResolvedPipeline } from \"./types\";\n\nconst DEFAULT_STAGES = [\n \"submitted\",\n \"paid_pending_vetting\",\n \"call_scheduled\",\n \"interviewed\",\n \"approved\",\n \"declined\",\n \"refunded\",\n] as const;\nconst DEFAULT_BOOKABLE = [\"submitted\", \"paid_pending_vetting\", \"call_scheduled\"] as const;\nconst DEFAULT_APPROVABLE = [\"paid_pending_vetting\", \"call_scheduled\", \"interviewed\"] as const;\n\n/**\n * Apply defaults + validate the pipeline config. With no config, the complete\n * reference pipeline. With `stages` given but the subsets omitted, the subsets\n * default to empty (a site opts in to bookable/approvable states explicitly).\n * Throws at import on a bad pipeline (empty/duplicate stages, an initial or a\n * subset entry not on the ladder).\n */\nexport function resolvePipeline(p: ChapterPipeline | undefined): ResolvedPipeline {\n const usingDefaults = !p?.stages;\n const stages = p?.stages ?? [...DEFAULT_STAGES];\n if (!Array.isArray(stages) || stages.length === 0 || !stages.every((s) => typeof s === \"string\" && s !== \"\")) {\n throw new Error(\"defineChapter.pipeline.stages: must be a non-empty array of status strings\");\n }\n if (new Set(stages).size !== stages.length) {\n throw new Error(\"defineChapter.pipeline.stages: statuses must be unique\");\n }\n const initial = p?.initial ?? (stages[0] as string);\n if (!stages.includes(initial)) {\n throw new Error(`defineChapter.pipeline.initial: \"${initial}\" is not one of the stages`);\n }\n const bookableFrom = p?.bookableFrom ?? (usingDefaults ? [...DEFAULT_BOOKABLE] : []);\n const approvableFrom = p?.approvableFrom ?? (usingDefaults ? [...DEFAULT_APPROVABLE] : []);\n for (const [name, subset] of [\n [\"bookableFrom\", bookableFrom],\n [\"approvableFrom\", approvableFrom],\n ] as const) {\n for (const s of subset) {\n if (!stages.includes(s)) throw new Error(`defineChapter.pipeline.${name}: \"${s}\" is not one of the stages`);\n }\n }\n return { stages, bookableFrom, approvableFrom, initial };\n}\n\n/** The ordinal of a status in the ladder, or -1 if unknown. */\nexport function stageIndex(status: string, p: ResolvedPipeline): number {\n return p.stages.indexOf(status);\n}\n\n/**\n * The status-never-moves-backwards invariant: a transition is allowed only when\n * both statuses are on the ladder and `to` is at or ahead of `from`. The worker\n * calls this before every status write; a violation is a 409, never a silent\n * downgrade.\n */\nexport function canTransition(from: string, to: string, p: ResolvedPipeline): boolean {\n const fi = p.stages.indexOf(from);\n const ti = p.stages.indexOf(to);\n return fi >= 0 && ti >= 0 && ti >= fi;\n}\n\n/** May an intro call be booked from this status? */\nexport function canBook(status: string, p: ResolvedPipeline): boolean {\n return p.bookableFrom.includes(status);\n}\n\n/** May an application be approved (→ member) from this status? */\nexport function canApprove(status: string, p: ResolvedPipeline): boolean {\n return p.approvableFrom.includes(status);\n}\n","import type { ChapterCopy } from \"./copy.js\";\n\nexport const DEFAULT_ADMIN_COPY: ChapterCopy[\"admin\"] = {\n auth: {\n checking: \"Checking access…\",\n notAuthorized: \"Not authorized\",\n accountNotAuthorized: \"{account} isn't on the admin list.\",\n thisAccount: \"This account\",\n signOut: \"Sign out\",\n loading: \"Loading…\",\n signInNotConfigured: \"Sign-in not configured\",\n missingPublishableKey: \"No Clerk publishable key is set for this environment yet.\",\n noWorkspaces: \"No admin workspaces are configured.\",\n signInTagline: \"Admin sign-in, invite only\",\n },\n shell: {\n adminRole: \"admin\",\n adminConsole: \"Admin Console\",\n adminName: \"Admin\",\n navigationLabel: \"Admin navigation\",\n },\n workspaces: {\n dashboard: \"Dashboard\",\n overview: \"Overview\",\n billing: \"Billing\",\n people: \"People\",\n admission: \"Admission\",\n network: \"Network\",\n portfolio: \"Portfolio\",\n settings: \"Settings\",\n calendar: \"Calendar\",\n email: \"Email\",\n chapters: \"Chapters\",\n formations: \"Formation applications\",\n dealFlow: \"Deal flow\",\n dashboardViewsLabel: \"Dashboard views\",\n settingsViewsLabel: \"Settings views\",\n collectionsLabel: \"CRM collections\",\n portfolioViewsLabel: \"Portfolio views\",\n },\n dashboard: {\n loading: \"Loading dashboard…\",\n loadFailed: \"Couldn't load the dashboard\",\n upcomingCalls: \"Upcoming calls\",\n callsNeedAttention: \"{count} need attention\",\n noUpcomingCalls: \"No upcoming calls.\",\n drift: \"drift\",\n open: \"Open\",\n meet: \"Meet\",\n applications: \"Applications\",\n newMembers: \"New members\",\n newMembersUnavailable: \"Appears once billing is connected.\",\n revenueAdded: \"Revenue · annual run rate added\",\n revenue: \"Revenue\",\n revenueUnavailable: \"Appears once billing is connected.\",\n pipeline: \"Pipeline\",\n pipelineLabel: \"Membership pipeline\",\n thisWeek: \"+{count} this week\",\n noChange: \"no change\",\n activeMemberships: \"Active memberships\",\n annualRunRate: \"Annual run rate\",\n testMode: \"test mode\",\n },\n billing: {\n loading: \"Loading…\",\n loadFailed: \"Couldn't load billing\",\n notConfigured: \"Billing isn't configured. No Stripe key is vaulted for this group.\",\n active: \"Active\",\n annualized: \"Annualized\",\n renewingSoon: \"Renewing within 60 days\",\n pastDue: \"Past due\",\n subscriptions: \"Subscriptions\",\n testMode: \"Stripe test mode\",\n truncated: \"Showing the first 100 subscriptions. The list is truncated.\",\n name: \"Name\",\n email: \"Email\",\n application: \"Application\",\n subscription: \"Subscription\",\n cancelling: \"cancelling\",\n amount: \"Amount\",\n renews: \"Renews\",\n },\n availability: {\n loading: \"Loading…\",\n loadFailed: \"Couldn't load availability\",\n saved: \"Saved.\",\n title: \"Booking availability\",\n days: \"Days\",\n startHour: \"Start hour (0–24)\",\n endHour: \"End hour (0–24)\",\n slotMinutes: \"Slot length (minutes)\",\n minNoticeHours: \"Minimum notice (hours)\",\n windowDays: \"Booking window (days)\",\n timezone: \"Timezone\",\n summaryTemplate: \"Event summary template\",\n save: \"Save availability\",\n dayLabels: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\n },\n email: {\n loading: \"Loading…\",\n loadFailed: \"Couldn't load email config\",\n saved: \"Saved.\",\n sent: \"Sent {template} to {address}{redirected}.\",\n testFailed: \"Test send did not deliver.\",\n delivery: \"Delivery\",\n notificationAddress: \"Notification address\",\n replyTo: \"Reply-to\",\n debugInbox: \"Debug inbox\",\n debugInboxHint: \"Non-production sends redirect here.\",\n sendTest: \"Send test\",\n enabled: \"Enabled\",\n subject: \"Subject\",\n body: \"Body\",\n save: \"Save changes\",\n sendLog: \"Send log\",\n sentColumn: \"Sent\",\n templateColumn: \"Template\",\n statusColumn: \"Status\",\n toColumn: \"To\",\n failed: \"failed\",\n redirected: \"redirected\",\n delivered: \"delivered\",\n },\n meetings: {\n loading: \"Loading…\",\n loadFailed: \"Couldn't load meetings\",\n cancelConfirm: \"Cancel this call? The calendar provider notifies the attendee.\",\n newStartPrompt: \"New start time (for example, 2026-08-01 14:00):\",\n parseFailed: \"Couldn't parse that time.\",\n agenda: \"Agenda\",\n empty: \"No meetings.\",\n unknown: \"(unknown)\",\n drift: \"drift\",\n meet: \"Meet\",\n reschedule: \"Reschedule\",\n cancel: \"Cancel\",\n },\n admission: {\n title: \"Interview decisions\",\n description: \"Local decisions override Parent decisions. Requiring an interview locally suppresses a Parent waiver for the same email.\",\n email: \"Email\",\n decision: \"Decision\",\n expires: \"Expires\",\n note: \"Internal note\",\n waive: \"Waive interview\",\n require: \"Require interview\",\n add: \"Add decision\",\n ledger: \"Effective grant ledger\",\n loading: \"Loading…\",\n consumed: \"consumed\",\n revoked: \"revoked\",\n expired: \"expired\",\n active: \"active\",\n local: \"local\",\n parent: \"Parent\",\n revoke: \"Revoke\",\n },\n network: {\n title: \"Share to a follower\",\n allowlistDescription: \"Sends the target's allowlisted fields. Its pipeline and account state remain local.\",\n sharing: \"Sharing…\",\n shareWith: \"Share with {target}\",\n shared: \"Shared with {target}.\",\n shareFailed: \"Could not share with {target}.\",\n deliveryFailed: \"Delivery failed.\",\n loadingRollup: \"Loading network overview…\",\n loadRollupFailed: \"Couldn't load the network overview\",\n overview: \"Network overview\",\n configuredFollowers: \"Configured followers\",\n reachableFollowers: \"Reachable followers\",\n recordsAcrossFollowers: \"Records across followers\",\n noFollowers: \"No follower sites are configured.\",\n followers: \"Followers\",\n available: \"available\",\n unavailable: \"unavailable\",\n recordTotals: \"Portfolio records\",\n noRecordTotals: \"No aggregate records are available yet.\",\n },\n records: {\n workflowMissing: \"This record is not linked to an application workflow.\",\n comms: \"Comms\",\n commsHistory: \"Comms history\",\n scheduling: \"Scheduling\",\n billing: \"Billing\",\n notes: \"Notes\",\n access: \"Access\",\n sharing: \"Sharing\",\n lifecycle: \"Access & lifecycle\",\n role: \"Role\",\n superAdminHint: \"Super-admin, managed in odla Studio.\",\n noAccount: \"No linked account yet. The role is set once they sign in.\",\n approve: \"Approve\",\n refund: \"Refund\",\n approved: \"Approved.\",\n refunded: \"Refund issued.\",\n roleSet: \"Role set to {role}.\",\n messageSent: \"Message sent.\",\n messageNotSent: \"Message was not sent.\",\n loadingTemplates: \"Loading templates…\",\n template: \"Template\",\n chooseTemplate: \"Choose a template…\",\n sending: \"Sending…\",\n send: \"Send\",\n noMessages: \"No messages recorded.\",\n message: \"Message\",\n newStartPrompt: \"New start time:\",\n parseFailed: \"Couldn't parse that time.\",\n cancelConfirm: \"Cancel this call?\",\n callCancelled: \"Call cancelled.\",\n callRescheduled: \"Call rescheduled.\",\n noApplication: \"No application is linked to this record.\",\n loadingMeetings: \"Loading meetings…\",\n noMeetings: \"No meetings recorded.\",\n joinMeeting: \"Join meeting\",\n openCalendar: \"Open calendar\",\n reschedule: \"Reschedule\",\n cancel: \"Cancel\",\n },\n};\n","import type { ChapterCopy } from \"./copy.js\";\n\nexport const DEFAULT_COMMON_COPY: ChapterCopy[\"common\"] = {\n loading: \"Loading…\",\n saved: \"Saved.\",\n unknown: \"(unknown)\",\n};\n\nexport const DEFAULT_JOIN_COPY: ChapterCopy[\"join\"] = {\n form: {\n submit: \"Submit application\",\n submitting: \"Submitting…\",\n submitFailed: \"Your application could not be submitted.\",\n unexpectedFailure: \"Something went wrong. Please try again.\",\n },\n booking: {\n unavailable: \"Scheduling is briefly unavailable. We'll reach out by email to arrange your call.\",\n loadFailed: \"Times are briefly unavailable. Please try again.\",\n slotTaken: \"That time was just taken. Here are the current openings.\",\n failed: \"The booking could not be completed.\",\n loading: \"Loading available times…\",\n book: \"Book this time\",\n booking: \"Booking…\",\n },\n payment: {\n setupFailed: \"Payment could not be set up. Please try again.\",\n preparing: \"Preparing secure payment…\",\n pending: \"Confirming your payment…\",\n processing: \"Processing…\",\n payAndContinue: \"Pay and continue\",\n incomplete: \"The payment did not complete. Please try again.\",\n consent: \"I have read and agree to the pricing and refund policy above.\",\n },\n done: {\n label: \"You're booked\",\n calendarInvite: \"A calendar invitation with the video call link is on its way to your email.\",\n memberArea: \"Go to your member area\",\n },\n accepted: {\n label: \"You're approved\",\n body: \"Your membership is approved. No introduction call is required.\",\n },\n gift: {\n chooseSelf: \"Buy membership for myself\",\n optionsLabel: \"Or give access to someone else\",\n label: \"Your gift code\",\n body: \"Share this one-time code with the recipient. It becomes active after payment is confirmed.\",\n save: \"Save it now. For security, this code is shown only once.\",\n rotate: \"Generate a new code\",\n rotateFailed: \"A new code could not be generated.\",\n },\n};\n\nexport const DEFAULT_MEMBERS_COPY: ChapterCopy[\"members\"] = {\n loadFailed: \"Sign in is briefly unavailable. Please refresh.\",\n account: {\n signOut: \"Sign out\",\n adminConsole: \"Admin console\",\n },\n provisional: {\n cardLabel: \"Your Application\",\n applicationNeeded: \"One step remains\",\n applicationNeededBody: \"Your account is ready, and the application that completes it takes a few minutes.\",\n apply: \"Apply for membership\",\n refunded: \"Membership refunded\",\n refundedBody: \"Your fee has been refunded in full and your membership is canceled.\",\n active: \"Your membership is active.\",\n renews: \"Your membership is active and renews {date}.\",\n introductionCall: \"Your introduction call\",\n calendarInvite: \"A calendar invitation with the video call link is in your email.\",\n joinCall: \"Join the video call\",\n bookCall: \"Book your introduction call\",\n bookCallBody: \"Your application is in. Choose a time below, and a calendar invitation will reach your email.\",\n chooseTime: \"Choose a time\",\n },\n full: {\n welcome: \"Welcome back.\",\n },\n gifts: {\n title: \"Give access\",\n body: \"Purchase access for someone else and share the one-time claim code.\",\n noneAvailable: \"No gift options are available right now.\",\n paid: \"Payment submitted. Save the code below while it is visible.\",\n saveCode: \"This code is shown once. Save it before leaving this page.\",\n purchases: \"Your gifts\",\n noPurchases: \"No gift purchases yet.\",\n pending: \"Pending\",\n redeemed: \"Redeemed\",\n expired: \"Expired\",\n revoked: \"Revoked\",\n rotate: \"Rotate code\",\n rotated: \"A new code was generated. Save it now.\",\n rotateFailed: \"The code could not be rotated.\",\n redeemTitle: \"Redeem a gift\",\n code: \"One-time code\",\n redeem: \"Redeem\",\n redeemFailed: \"The code is invalid or unavailable.\",\n },\n reschedule: {\n changeTime: \"Change your time\",\n unavailable: \"Scheduling is briefly unavailable. We'll reach out by email to arrange your call.\",\n loadFailed: \"Times are briefly unavailable. Please try again.\",\n slotGone: \"That time is no longer available. Please pick another.\",\n loading: \"Loading available times…\",\n noTimes: \"No open times right now. Please check back soon.\",\n rescheduling: \"Rescheduling…\",\n keepTime: \"Keep my current time\",\n },\n};\n","import { DEFAULT_ADMIN_COPY } from \"./copy-defaults-admin.js\";\nimport {\n DEFAULT_COMMON_COPY,\n DEFAULT_JOIN_COPY,\n DEFAULT_MEMBERS_COPY,\n} from \"./copy-defaults.js\";\nimport type { ChapterCopy, ChapterCopyInput } from \"./copy.js\";\n\n/** Complete default language resolved beneath partial Chapter copy overrides. */\nexport const DEFAULT_CHAPTER_COPY: ChapterCopy = {\n common: DEFAULT_COMMON_COPY,\n join: DEFAULT_JOIN_COPY,\n members: DEFAULT_MEMBERS_COPY,\n admin: DEFAULT_ADMIN_COPY,\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n\nfunction mergeCopy<T>(base: T, input: unknown, path: string): T {\n if (typeof base === \"string\") {\n if (input === undefined) return base;\n if (typeof input !== \"string\") throw new Error(`${path}: must be a string`);\n return input as T;\n }\n if (Array.isArray(base)) {\n if (input === undefined) return [...base] as T;\n if (!Array.isArray(input) || !input.every((item) => typeof item === \"string\")) {\n throw new Error(`${path}: must be an array of strings`);\n }\n return [...input] as T;\n }\n if (!isObject(base)) return base;\n if (input !== undefined && !isObject(input)) throw new Error(`${path}: must be an object`);\n const overrides = input as Record<string, unknown> | undefined;\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(base)) {\n result[key] = mergeCopy(value, overrides?.[key], `${path}.${key}`);\n }\n return result as T;\n}\n\n/** Resolve a partial copy contract and validate every supplied leaf. */\nexport function resolveChapterCopy(input?: ChapterCopyInput): ChapterCopy {\n return mergeCopy(DEFAULT_CHAPTER_COPY, input, \"defineChapter.copy\");\n}\n\n/** Replace `{name}` placeholders without interpreting the resulting text as HTML. */\nexport function formatChapterCopy(\n template: string,\n values: Readonly<Record<string, string | number>>,\n): string {\n return template.replace(/\\{([a-zA-Z][a-zA-Z0-9]*)\\}/g, (match, key: string) =>\n Object.prototype.hasOwnProperty.call(values, key) ? String(values[key]) : match,\n );\n}\n","import type { Crm, FieldConditions, FieldDef, FieldType } from \"@odla-ai/crm\";\nimport type { Chapter, ResolvedApplication, ResolvedLeaderFormation } from \"./types\";\n\n/** Current public schema version for Chapter flow-field contracts. */\nexport const CHAPTER_FLOW_FIELDS_SCHEMA_VERSION = 1 as const;\n\n/** Configurable Chapter intake journeys that publish field contracts. */\nexport type ChapterFieldFlow = \"join\" | \"formation\";\n\n/** Email comparison policy advertised by an email field. */\nexport type ChapterEmailIdentity = \"literal\";\n\n/**\n * One effective field in a Chapter intake journey.\n *\n * IDs, value types, and options come from the follower-declared schema. A hub\n * or CMS may select, order, and configure only those declared fields; it cannot\n * use this presentation document to add storage or widen follower authority.\n */\nexport interface ChapterFlowField {\n id: string;\n label: string;\n type: FieldType;\n required: boolean;\n order: number;\n maxLength?: number;\n options?: readonly string[];\n conditions?: FieldConditions;\n /** Present only for an email identity field. Aliases such as `+tag` remain significant. */\n emailIdentity?: ChapterEmailIdentity;\n}\n\n/** Ordered, versioned effective field state for one Chapter journey. */\nexport interface ChapterFlowFieldContract {\n schemaVersion: typeof CHAPTER_FLOW_FIELDS_SCHEMA_VERSION;\n flow: ChapterFieldFlow;\n fields: readonly ChapterFlowField[];\n}\n\nconst APPLICATION_LABELS: Readonly<Record<string, string>> = {\n firstName: \"First name\",\n lastName: \"Last name\",\n email: \"Email\",\n referral: \"Referral source\",\n referralName: \"Referral name\",\n whoYouAre: \"Who you are\",\n linkedin: \"LinkedIn\",\n message: \"Intro message\",\n phone: \"Phone\",\n state: \"State\",\n};\n\nfunction humanize(id: string): string {\n const text = id.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\").replace(/[_-]+/g, \" \").trim();\n return text ? `${text[0]!.toUpperCase()}${text.slice(1)}` : id;\n}\n\nfunction applicationDefs(chapter: Chapter): Record<string, FieldDef> {\n try {\n return chapter.crm.type(\"person\").fields;\n } catch {\n return {};\n }\n}\n\nfunction applicationType(id: string, def: FieldDef | undefined): FieldType {\n // Application rows accept configurable strings. Preserve the richer\n // string-like CRM hints without claiming that a numeric/date/json CRM field\n // changes the application storage contract.\n if (def && [\"string\", \"email\", \"url\", \"enum\"].includes(def.type)) return def.type;\n return id === \"email\" ? \"email\" : id === \"linkedin\" ? \"url\" : \"string\";\n}\n\n/** Resolve the exact ordered fields accepted by the membership application flow. */\nexport function applicationFlowFields(\n chapter: Chapter,\n application: ResolvedApplication = chapter.application,\n): ChapterFlowField[] {\n const defs = applicationDefs(chapter);\n return [...application.required, ...application.optional].map((id, order) => {\n const def = defs[id];\n const conditions = application.conditions[id];\n const type = applicationType(id, def);\n return {\n id,\n label: def?.label ?? APPLICATION_LABELS[id] ?? humanize(id),\n type,\n required: application.required.includes(id),\n order,\n maxLength: application.maxLen[id] ?? application.defaultMaxLen,\n ...(type === \"enum\" && def?.options ? { options: [...def.options] } : {}),\n ...(conditions ? { conditions: { ...conditions } } : {}),\n ...(type === \"email\" ? { emailIdentity: \"literal\" as const } : {}),\n };\n });\n}\n\n/** Common resolver retained separately so the legacy formationFields helper cannot drift. */\nexport function resolveFormationFlowFields(\n crm: Crm,\n formation: ResolvedLeaderFormation,\n): ChapterFlowField[] {\n if (!formation.enabled) return [];\n const def = crm.type(formation.type);\n return [...formation.required, ...formation.optional].map((id, order) => {\n const field = def.fields[id]!;\n return {\n id,\n label: field.label ?? humanize(id),\n type: field.type,\n required: formation.required.includes(id),\n order,\n maxLength: formation.maxLen[id] ?? formation.defaultMaxLen,\n ...(field.options ? { options: [...field.options] } : {}),\n ...(id === def.emailField || field.type === \"email\" ? { emailIdentity: \"literal\" as const } : {}),\n };\n });\n}\n\n/** Resolve the exact ordered fields accepted by the chapter-formation flow. */\nexport function formationFlowFields(\n chapter: Chapter,\n formation: ResolvedLeaderFormation = chapter.formation,\n): ChapterFlowField[] {\n return resolveFormationFlowFields(chapter.crm, formation);\n}\n\n/**\n * Build the public field contract consumed by follower forms and CMS previews.\n * The optional application is the already-authorized effective selection from\n * signup control; it never expands the follower's declared application schema.\n */\nexport function chapterFlowFieldContract(\n chapter: Chapter,\n flow: ChapterFieldFlow,\n application: ResolvedApplication = chapter.application,\n): ChapterFlowFieldContract {\n return {\n schemaVersion: CHAPTER_FLOW_FIELDS_SCHEMA_VERSION,\n flow,\n fields: flow === \"join\"\n ? applicationFlowFields(chapter, application)\n : formationFlowFields(chapter),\n };\n}\n","import type { Crm } from \"@odla-ai/crm\";\nimport type { LeaderFormationConfig, ResolvedLeaderFormation } from \"./types\";\nimport { resolveFormationFlowFields } from \"./flow-fields\";\n\nconst DEFAULT_REQUIRED = [\"name\", \"email\", \"location\", \"thesis\"];\nconst DEFAULT_OPTIONAL = [\"proposedChapter\", \"experience\", \"collaborators\"];\n\n/** Resolve and validate the public chapter-formation intake contract. */\nexport function resolveLeaderFormation(\n input: LeaderFormationConfig | undefined,\n crm: Crm,\n): ResolvedLeaderFormation {\n const type = input?.type ?? \"chapter_application\";\n if (!input) {\n return {\n enabled: false,\n type,\n required: [],\n optional: [],\n maxLen: {},\n defaultMaxLen: 4000,\n bodyCap: 32768,\n };\n }\n const def = crm.config.types[type];\n if (!def) throw new Error(`defineChapter.formation.type: unknown CRM type \"${type}\"`);\n const required = input.required ?? (type === \"chapter_application\" ? DEFAULT_REQUIRED : []);\n const optional = input.optional ?? (type === \"chapter_application\" ? DEFAULT_OPTIONAL : []);\n for (const [name, values] of [[\"required\", required], [\"optional\", optional]] as const) {\n if (!Array.isArray(values) || !values.every((field) => typeof field === \"string\" && field !== \"\")) {\n throw new Error(`defineChapter.formation.${name}: must be an array of field-name strings`);\n }\n }\n const duplicates = [...required, ...optional].filter((field, index, fields) => fields.indexOf(field) !== index);\n if (duplicates.length) throw new Error(`defineChapter.formation: duplicate public field \"${duplicates[0]}\"`);\n const unknown = [...required, ...optional].filter((field) => !def.fields[field]);\n if (unknown.length) throw new Error(`defineChapter.formation: field \"${unknown[0]}\" is not declared on CRM type \"${type}\"`);\n const missingRequired = Object.entries(def.fields)\n .filter(([, field]) => field.required)\n .map(([field]) => field)\n .filter((field) => !required.includes(field));\n if (missingRequired.length) {\n throw new Error(`defineChapter.formation.required: must include required CRM field \"${missingRequired[0]}\"`);\n }\n const unsupportedRequired = required.find((field) =>\n ![\"string\", \"email\", \"url\", \"enum\"].includes(def.fields[field]!.type));\n if (unsupportedRequired) {\n throw new Error(`defineChapter.formation.required: field \"${unsupportedRequired}\" must be string-like`);\n }\n if (required.length === 0) throw new Error(\"defineChapter.formation.required: must not be empty\");\n const defaultMaxLen = input.defaultMaxLen ?? 4000;\n const bodyCap = input.bodyCap ?? 32768;\n if (!Number.isSafeInteger(defaultMaxLen) || defaultMaxLen < 1 || defaultMaxLen > 32768) {\n throw new Error(\"defineChapter.formation.defaultMaxLen: must be an integer from 1 to 32768\");\n }\n if (!Number.isSafeInteger(bodyCap) || bodyCap < 1024 || bodyCap > 131072) {\n throw new Error(\"defineChapter.formation.bodyCap: must be an integer from 1024 to 131072\");\n }\n for (const [field, cap] of Object.entries(input.maxLen ?? {})) {\n if (![...required, ...optional].includes(field) || !Number.isSafeInteger(cap) || cap < 1 || cap > 32768) {\n throw new Error(`defineChapter.formation.maxLen.${field}: must name a public field and be an integer from 1 to 32768`);\n }\n }\n return {\n enabled: true,\n type,\n required,\n optional,\n maxLen: input.maxLen ?? {},\n defaultMaxLen,\n bodyCap,\n };\n}\n\n/** Public, presentational field metadata for a host-owned intake form. */\nexport function formationFields(\n crm: Crm,\n formation: ResolvedLeaderFormation,\n): import(\"./flow-fields\").ChapterFlowField[] {\n return resolveFormationFlowFields(crm, formation);\n}\n","import type { Crm } from \"@odla-ai/crm\";\nimport type {\n ChapterConfig,\n ResolvedNetwork,\n ResolvedNetworkReader,\n ResolvedNetworkTarget,\n} from \"./types\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst FIELD = /^[a-z][a-zA-Z0-9_]*$/;\nconst BINDING = /^[A-Z][A-Z0-9_]{0,127}$/;\n\nfunction validateSharedNotes(opts: {\n path: string;\n values: readonly string[];\n crm: Crm;\n fields?: Record<string, readonly string[]>;\n}) {\n const duplicate = opts.values.some((type, index) => opts.values.indexOf(type) !== index);\n const invalid = opts.values.some((type) =>\n !FIELD.test(type) || !opts.crm.config.types[type] || (opts.fields ? !opts.fields[type] : false));\n if (duplicate || invalid) {\n throw new Error(`${opts.path}: must contain unique CRM types allowed by fields`);\n }\n}\n\n/** Resolve the two-sided federation contract. Targets are leader-owned\n * outbound policy; readers are follower-owned disclosure/write policy. */\nexport function resolveNetwork(config: ChapterConfig, crm: Crm): ResolvedNetwork {\n const seen = new Set<string>();\n const targets: ResolvedNetworkTarget[] = [];\n for (const target of config.network?.targets ?? []) {\n if (!SLUG.test(target.id)) {\n throw new Error(`defineChapter.network.targets.id: must be a lowercase slug — got ${JSON.stringify(target.id)}`);\n }\n if (seen.has(target.id)) throw new Error(`defineChapter.network.targets: duplicate target \"${target.id}\"`);\n seen.add(target.id);\n let url: URL;\n try {\n url = new URL(target.url);\n } catch {\n throw new Error(`defineChapter.network.targets.${target.id}.url: must be an absolute URL`);\n }\n const local = url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"::1\";\n if (url.protocol !== \"https:\" && !(local && url.protocol === \"http:\")) {\n throw new Error(`defineChapter.network.targets.${target.id}.url: must use https (http is allowed only for localhost)`);\n }\n const fields = target.fields;\n for (const [type, names] of Object.entries(fields ?? {})) {\n if (!FIELD.test(type) || names.length === 0 || names.some((name) => !FIELD.test(name))) {\n throw new Error(\n `defineChapter.network.targets.${target.id}.fields.${type}: type and field names must be non-empty CRM identifiers`,\n );\n }\n const def = crm.config.types[type];\n if (!def) throw new Error(`defineChapter.network.targets.${target.id}.fields: unknown leader CRM type \"${type}\"`);\n const unknown = names.filter((field) => !def.fields[field]);\n if (unknown.length > 0) {\n throw new Error(\n `defineChapter.network.targets.${target.id}.fields.${type}: ${unknown.map((field) => `\"${field}\"`).join(\", \")} ` +\n \"not declared on the leader CRM type\",\n );\n }\n const nameField = def.nameField ?? \"name\";\n if (!names.includes(nameField)) {\n throw new Error(\n `defineChapter.network.targets.${target.id}.fields.${type}: must include required name field \"${nameField}\"`,\n );\n }\n }\n const secretName = target.secretName?.trim() || `network_share_${target.id.replaceAll(\"-\", \"_\")}`;\n if (!/^[a-zA-Z][a-zA-Z0-9_-]{1,127}$/.test(secretName)) {\n throw new Error(`defineChapter.network.targets.${target.id}.secretName: must be a vault-key identifier`);\n }\n const binding = target.binding?.trim();\n if (binding && !BINDING.test(binding)) {\n throw new Error(\n `defineChapter.network.targets.${target.id}.binding: must be an uppercase Worker binding identifier`,\n );\n }\n const sharedNotes = target.sharedNotes ?? [];\n validateSharedNotes({\n path: `defineChapter.network.targets.${target.id}.sharedNotes`,\n values: sharedNotes,\n crm,\n fields,\n });\n targets.push({\n id: target.id,\n name: target.name?.trim() || target.id,\n url: url.origin,\n ...(binding ? { binding } : {}),\n secretName,\n ...(fields ? { fields } : {}),\n sharedNotes,\n });\n }\n const readerIds = new Set<string>();\n const readers: ResolvedNetworkReader[] = [];\n for (const reader of config.network?.readers ?? []) {\n if (!SLUG.test(reader.id)) {\n throw new Error(`defineChapter.network.readers.id: must be a lowercase slug — got ${JSON.stringify(reader.id)}`);\n }\n if (readerIds.has(reader.id)) {\n throw new Error(`defineChapter.network.readers: duplicate reader \"${reader.id}\"`);\n }\n readerIds.add(reader.id);\n const entries = Object.entries(reader.fields ?? {});\n if (entries.length === 0) {\n throw new Error(`defineChapter.network.readers.${reader.id}.fields: at least one CRM type is required`);\n }\n for (const [type, names] of entries) {\n if (!FIELD.test(type) || names.length === 0 || names.some((name) => !FIELD.test(name))) {\n throw new Error(\n `defineChapter.network.readers.${reader.id}.fields.${type}: type and field names must be non-empty CRM identifiers`,\n );\n }\n const def = crm.config.types[type];\n if (!def) {\n throw new Error(`defineChapter.network.readers.${reader.id}.fields: unknown local CRM type \"${type}\"`);\n }\n const unknown = names.filter((field) => !def.fields[field]);\n if (unknown.length > 0) {\n throw new Error(\n `defineChapter.network.readers.${reader.id}.fields.${type}: ` +\n `${unknown.map((field) => `\"${field}\"`).join(\", \")} not declared on the local CRM type`,\n );\n }\n const nameField = def.nameField ?? \"name\";\n if (!names.includes(nameField)) {\n throw new Error(\n `defineChapter.network.readers.${reader.id}.fields.${type}: must include required name field \"${nameField}\"`,\n );\n }\n }\n const sharedNotes = reader.sharedNotes ?? [];\n validateSharedNotes({\n path: `defineChapter.network.readers.${reader.id}.sharedNotes`,\n values: sharedNotes,\n crm,\n fields: reader.fields,\n });\n readers.push({ id: reader.id, fields: reader.fields, sharedNotes });\n }\n return { targets, readers };\n}\n","import type { ChapterSignupControl, ResolvedSignupControl } from \"./types-signup-control\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst SECRET_NAME = /^[a-z][a-z0-9_]{1,127}$/;\n\n/** Validate one deliberately separate signup-control edge. */\nexport function resolveSignupControl(\n input: ChapterSignupControl | undefined,\n): ResolvedSignupControl | null {\n if (!input) return null;\n if (!SLUG.test(input.sourceId)) {\n throw new Error(\"defineChapter.signupControl.sourceId: must be a lowercase app slug\");\n }\n if (input.stripeMode !== \"test\" && input.stripeMode !== \"live\") {\n throw new Error('defineChapter.signupControl.stripeMode: must be \"test\" or \"live\"');\n }\n const secretName = input.secretName?.trim() || \"signup_control_secret\";\n if (!SECRET_NAME.test(secretName)) {\n throw new Error(\"defineChapter.signupControl.secretName: must be a vault-key identifier\");\n }\n return { sourceId: input.sourceId, secretName, stripeMode: input.stripeMode };\n}\n","import type { ChapterMemberContent, ResolvedMemberContent } from \"./types-member-content\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst SECRET_NAME = /^[a-z][a-z0-9_]{1,127}$/;\n\n/** Validate the deliberately separate member-content authoring boundary. */\nexport function resolveMemberContent(input: ChapterMemberContent | undefined): ResolvedMemberContent | null {\n if (!input) return null;\n const parent = input.parent;\n if (parent && !SLUG.test(parent.sourceId)) {\n throw new Error(\"defineChapter.memberContent.parent.sourceId: must be a lowercase app slug\");\n }\n const secretName = parent?.secretName?.trim() || \"member_content_control_secret\";\n if (parent && !SECRET_NAME.test(secretName)) {\n throw new Error(\"defineChapter.memberContent.parent.secretName: must be a vault-key identifier\");\n }\n return {\n enabled: true,\n localAuthoring: input.localAuthoring !== false,\n parent: parent ? { sourceId: parent.sourceId, secretName } : null,\n };\n}\n","// Reusable CRM records for a leader that forms and operates a portfolio of\n// chapters. This is configuration, not a second data engine: every record still\n// uses @odla-ai/crm's normal CRUD, pipelines, activities, views, and relations.\nimport { composeCrmConfigs, type CrmConfig, type TypeDef } from \"@odla-ai/crm\";\nimport { defaultCrm } from \"./defaults\";\n\n/** Options for {@link leaderCrmConfig}. */\nexport interface LeaderCrmOptions {\n /** Existing host CRM config to preserve. Defaults to Chapter's people +\n * businesses graph for hub mode. */\n base?: CrmConfig;\n /** Host-owned additions or replacements for the durable chapter record.\n * Fields and facets merge with the preset; a supplied pipeline replaces the\n * generic proposed/forming/active lifecycle. The final composed CRM still\n * goes through defineCrm's normal validation. */\n chapter?: Partial<TypeDef>;\n}\n\n/**\n * Add generic chapter-formation, portfolio, and deal-flow records to an\n * existing CRM. Collisions fail through `composeCrmConfigs`, so this preset\n * never silently replaces a host's people pipeline or templates.\n */\nexport function leaderCrmConfig(options: LeaderCrmOptions = {}): CrmConfig {\n const base = options.base ?? defaultCrm(\"hub\");\n const defaultChapter: TypeDef = {\n label: \"Chapter\",\n labelPlural: \"Chapters\",\n workspace: \"portfolio\",\n nameField: \"name\",\n fields: {\n name: { type: \"string\", label: \"Name\", required: true },\n slug: { type: \"string\", label: \"Slug\", slot: \"s1\" },\n region: { type: \"string\", label: \"Region\", slot: \"s2\" },\n url: { type: \"url\", label: \"Website\" },\n thesis: { type: \"string\", label: \"Investment thesis\" },\n launchedAt: { type: \"date\", label: \"Launch date\", slot: \"d1\" },\n notes: { type: \"string\", label: \"Notes\" },\n },\n pipeline: {\n stages: [\n { id: \"proposed\", label: \"Proposed\" },\n { id: \"forming\", label: \"Forming\" },\n { id: \"active\", label: \"Active\" },\n { id: \"paused\", label: \"Paused\" },\n { id: \"closed\", label: \"Closed\", terminal: true },\n ],\n transitions: {\n proposed: [\"forming\", \"closed\"],\n forming: [\"active\", \"paused\", \"closed\"],\n active: [\"paused\", \"closed\"],\n paused: [\"forming\", \"active\", \"closed\"],\n },\n },\n facets: { rank: \"manual\" },\n };\n const chapterOverride = options.chapter ?? {};\n const chapterType: TypeDef = {\n ...defaultChapter,\n ...chapterOverride,\n fields: {\n ...defaultChapter.fields,\n ...(chapterOverride.fields ?? {}),\n // The preset's natural identity is not optional even when the host adds\n // its own fields or relabels the name input.\n name: {\n ...defaultChapter.fields.name,\n ...(chapterOverride.fields?.name ?? {}),\n type: \"string\",\n required: true,\n },\n },\n facets: {\n ...defaultChapter.facets,\n ...(chapterOverride.facets ?? {}),\n },\n };\n const portfolio: CrmConfig = {\n types: {\n chapter: chapterType,\n chapter_application: {\n label: \"Chapter application\",\n labelPlural: \"Formation applications\",\n workspace: \"portfolio\",\n nameField: \"name\",\n emailField: \"email\",\n fields: {\n name: { type: \"string\", label: \"Applicant name\", required: true },\n email: { type: \"email\", label: \"Email\", required: true },\n location: { type: \"string\", label: \"Location\", required: true, slot: \"s1\" },\n proposedChapter: { type: \"string\", label: \"Proposed chapter\", slot: \"s2\" },\n thesis: { type: \"string\", label: \"Proposed thesis\", required: true },\n experience: { type: \"string\", label: \"Relevant experience\" },\n collaborators: { type: \"json\", label: \"Collaborators\" },\n notes: { type: \"string\", label: \"Internal notes\" },\n },\n pipeline: {\n stages: [\n { id: \"submitted\", label: \"Submitted\" },\n { id: \"reviewing\", label: \"Reviewing\" },\n { id: \"interviewing\", label: \"Interviewing\" },\n { id: \"approved\", label: \"Approved\" },\n { id: \"forming\", label: \"Forming\" },\n { id: \"declined\", label: \"Declined\", terminal: true },\n ],\n transitions: {\n submitted: [\"reviewing\", \"declined\"],\n reviewing: [\"interviewing\", \"approved\", \"declined\"],\n interviewing: [\"approved\", \"declined\"],\n approved: [\"forming\", \"declined\"],\n },\n },\n facets: { email: true, rank: \"manual\" },\n },\n deal: {\n label: \"Deal\",\n labelPlural: \"Deal flow\",\n workspace: \"portfolio\",\n nameField: \"name\",\n fields: {\n name: { type: \"string\", label: \"Company or deal\", required: true },\n chapter: { type: \"string\", label: \"Source chapter\", slot: \"s1\" },\n sector: { type: \"string\", label: \"Sector\", slot: \"s2\" },\n source: { type: \"string\", label: \"Source\", slot: \"s3\" },\n website: { type: \"url\", label: \"Website\" },\n amount: { type: \"number\", label: \"Target amount\", slot: \"n1\" },\n notes: { type: \"string\", label: \"Notes\" },\n },\n pipeline: {\n stages: [\n { id: \"sourced\", label: \"Sourced\" },\n { id: \"screening\", label: \"Screening\" },\n { id: \"diligence\", label: \"Diligence\" },\n { id: \"committee\", label: \"Committee\" },\n { id: \"offered\", label: \"Offered\" },\n { id: \"invested\", label: \"Invested\", terminal: true },\n { id: \"passed\", label: \"Passed\", terminal: true },\n ],\n transitions: {\n sourced: [\"screening\", \"passed\"],\n screening: [\"diligence\", \"committee\", \"passed\"],\n diligence: [\"committee\", \"offered\", \"passed\"],\n committee: [\"offered\", \"passed\"],\n offered: [\"invested\", \"passed\"],\n passed: [\"sourced\"],\n },\n },\n facets: { rank: \"manual\" },\n },\n },\n relations: {\n formation_result: {\n from: \"chapter_application\",\n to: \"chapter\",\n label: \"formed as\",\n reverseLabel: \"formation application\",\n },\n chapter_deal: {\n from: \"deal\",\n to: \"chapter\",\n label: \"sourced by\",\n reverseLabel: \"deal flow\",\n },\n },\n };\n if (base.types.company) {\n portfolio.relations!.deal_company = {\n from: \"deal\",\n to: \"company\",\n label: \"concerns\",\n reverseLabel: \"deals\",\n };\n }\n if (base.types.person) {\n portfolio.relations!.application_contact = {\n from: \"person\",\n to: \"chapter_application\",\n label: \"submitted\",\n reverseLabel: \"applicant\",\n };\n }\n return composeCrmConfigs(base, portfolio);\n}\n","// The CLI-consumable provisioning descriptor. It composes @odla-ai/crm's\n// integration (crm_* namespaces + crm_config seed + route probe) with the\n// chapter's own namespaces and a guarded `groups`-row seed, so a site's\n// odla.config.mjs lists ONE integration. The CLI reads it structurally\n// (matching OdlaIntegration) and merges schema/rules by namespace.\nimport { createCrmIntegration } from \"@odla-ai/crm\";\nimport { buildTierSeeds } from \"./tiers\";\nimport type { Chapter } from \"./types\";\n\n/** Options for {@link createChapterIntegration}. */\nexport interface ChapterIntegrationOptions {\n /** CRM route mount point. Default \"/api/crm\". */\n basePath?: string;\n /** Seed timestamp override for reproducible builds/tests. */\n now?: number;\n}\n\ninterface IntegrationSeed {\n id: string;\n ns: string;\n key: { attr: string; value: string };\n attrs: Record<string, unknown>;\n}\n\n/** Structural match for the CLI's `OdlaIntegration`. */\nexport interface ChapterIntegrationDescriptor {\n id: string;\n title: string;\n npm: string;\n schema: { entities: Record<string, unknown>; links: Record<string, unknown> };\n rules: Record<string, unknown>;\n seeds: IntegrationSeed[];\n probes: Array<{ path: string; expectedStatus: number }>;\n /** Runbooks that bear on THIS chapter's role, so tooling can point at the\n * right procedure without the operator knowing it exists. A chapter declaring\n * `network.targets` is a leader hub; one with no targets is a follower site\n * (and may declare `network.readers` for bounded CRM browsing). */\n runbooks: ChapterRunbookHints;\n}\n\n/** Which runbooks apply, and why. */\nexport interface ChapterRunbookHints {\n role: \"leader\" | \"follower\";\n /** Platform runbook slugs, most relevant first. */\n slugs: string[];\n /** One line a human or agent can act on. */\n guidance: string;\n}\n\n/**\n * Build the one CLI-consumable integration for a chapter/hub: the crm_*\n * namespaces + crm_config seed + route probe, merged with the chapter's own\n * namespaces and a guarded `groups`-row seed. Drop it in odla.config.mjs's\n * `integrations` array.\n */\nexport function createChapterIntegration(\n chapter: Chapter,\n options: ChapterIntegrationOptions = {},\n): ChapterIntegrationDescriptor {\n const basePath = options.basePath ?? \"/api/crm\";\n const now = options.now ?? Date.now();\n const emails = chapter.config.emails;\n\n const crmDesc = createCrmIntegration(chapter.crm, {\n basePath,\n now,\n ...(emails?.notificationEmail ? { notificationEmail: emails.notificationEmail } : {}),\n ...(emails?.replyTo ? { replyTo: emails.replyTo } : {}),\n ...(emails?.debugEmail ? { debugEmail: emails.debugEmail } : {}),\n });\n\n const seeds: IntegrationSeed[] = [...(crmDesc.seeds ?? [])];\n const group = chapter.groupSeed();\n if (group) {\n seeds.push({ id: \"group\", ns: \"groups\", key: { attr: \"id\", value: chapter.id }, attrs: { ...group, createdAt: now } });\n // One insert-only seed per declared tier, keyed by its own id so re-running\n // provisioning never duplicates a tier or overwrites a price an owner has\n // since changed in Studio.\n for (const tier of buildTierSeeds(chapter.id, chapter.config.tiers, now)) {\n seeds.push({\n id: `tier:${String(tier.id)}`,\n ns: \"tiers\",\n key: { attr: \"id\", value: String(tier.id) },\n attrs: tier,\n });\n }\n }\n\n // A leader declares where it pushes records. A follower declares no targets;\n // it may still declare readers for bounded record browsing.\n const isLeader = (chapter.config.network?.targets?.length ?? 0) > 0;\n const runbooks: ChapterRunbookHints = isLeader\n ? {\n role: \"leader\",\n slugs: [\"chapter-leader\", \"chapter-network\", \"crm\"],\n guidance:\n `${chapter.name} is a LEADER hub: it holds the CRM and shares records with its chapters. ` +\n `Read it with \\`odla-ai runbook get chapter-leader\\`.`,\n }\n : {\n role: \"follower\",\n slugs: [\"chapter-follower\", \"chapter-network\"],\n guidance:\n `${chapter.name} is a FOLLOWER site: it receives people and records from a leader hub. ` +\n `Read it with \\`odla-ai runbook get chapter-follower\\`.`,\n };\n\n return {\n id: \"chapter\",\n title: `Chapter: ${chapter.name}`,\n npm: \"@odla-ai/chapter\",\n schema: {\n entities: { ...crmDesc.schema.entities, ...chapter.schema.entities },\n links: { ...crmDesc.schema.links, ...chapter.schema.links },\n },\n rules: { ...crmDesc.rules, ...chapter.rules },\n seeds,\n probes: [\n ...(crmDesc.probes ?? []),\n // The snapshot route is deliberately private. A credential-free smoke\n // request must prove that the route is mounted and closed.\n { path: \"/api/network/snapshot\", expectedStatus: 401 },\n ...(chapter.network.readers.length > 0\n ? [{ path: \"/api/network/records\", expectedStatus: 401 }]\n : []),\n ...(chapter.network.readers.some((reader) => reader.sharedNotes.length > 0)\n ? [{\n path: \"/api/network/shared-notes\",\n expectedStatus: 401,\n }]\n : []),\n // Formation metadata is public only when the host explicitly enables\n // the bounded intake contract.\n ...(chapter.formation.enabled\n ? [{ path: \"/api/formation/config\", expectedStatus: 200 }]\n : []),\n ...(chapter.memberContent\n ? [\n { path: \"/api/member-content\", expectedStatus: 401 },\n { path: \"/api/admin/member-content\", expectedStatus: 401 },\n ]\n : []),\n ],\n runbooks,\n };\n}\n","// Membership tiers. A chapter offers one or more tiers, and a tier — not the\n// group — decides what a member pays. Keeping the price on the tier is what\n// makes a free tier expressible: `paymentsReady` used to gate the whole join\n// flow on the group holding a Stripe price, so a £0 membership was unjoinable.\n//\n// Everything here is pure so the join page, the checkout route and the seeder\n// agree about which tiers exist and which of them can actually be bought.\n\n/** One membership tier a chapter offers. `priceCents: 0` means free. */\nexport interface ChapterTier {\n /** Stable slug, referenced by `applications.tierId`. Never renumbered. */\n id: string;\n /** The group this tier belongs to. */\n groupId: string;\n /** Display name, e.g. \"Founding\". */\n name: string;\n /** Price in minor units. `0` is free and needs no Stripe price. */\n priceCents: number;\n /** Stripe price to subscribe. Required only when `priceCents > 0`. */\n stripePriceId?: string | null;\n /** Short description shown beside the tier on the join page. */\n blurb?: string;\n /** Ascending display order; ties fall back to `id` for a stable sort. */\n sortOrder: number;\n /** An inactive tier is retained for existing members but never offered. */\n active: boolean;\n}\n\n/**\n * A tier as declared in `defineChapter`, before it becomes a row.\n *\n * `groupId` is absent here because the chapter owns exactly one group at seed\n * time; the seeder fills it in.\n */\nexport interface ChapterTierConfig {\n id: string;\n name: string;\n priceCents: number;\n stripePriceId?: string;\n blurb?: string;\n /** Defaults to declaration order when omitted. */\n sortOrder?: number;\n /** Defaults to true; set false to retire a tier without deleting it. */\n active?: boolean;\n}\n\n/** Build the seed rows for a chapter's declared tiers. */\nexport function buildTierSeeds(\n groupId: string,\n configured: readonly ChapterTierConfig[] = [],\n now = 0,\n): Array<Record<string, unknown>> {\n return configured.map((tier, index) => ({\n id: tier.id,\n groupId,\n name: tier.name,\n priceCents: tier.priceCents,\n ...(tier.stripePriceId ? { stripePriceId: tier.stripePriceId } : {}),\n ...(tier.blurb ? { blurb: tier.blurb } : {}),\n sortOrder: tier.sortOrder ?? index,\n active: tier.active !== false,\n createdAt: now,\n }));\n}\n\n/** The `groups`-row fields tier payability depends on. */\nexport interface TierGroup {\n id?: string;\n stripePublishableKey?: string | null;\n /** Legacy single price, used only to synthesize an implicit tier. */\n stripePriceId?: string | null;\n standardPriceCents?: number;\n foundingDiscountCents?: number;\n}\n\n/**\n * Whether this tier costs nothing. A free tier never touches Stripe.\n *\n * Free means both no price AND no Stripe price to charge against. The second\n * half matters for chapters that predate tiers: a group can carry a real\n * `stripePriceId` while `standardPriceCents` is 0, because the cents field is\n * display copy and the amount actually lives in Stripe. Reading such a group as\n * free would silently stop charging an existing paying chapter.\n */\nexport function tierIsFree(\n tier: Pick<ChapterTier, \"priceCents\"> & { stripePriceId?: string | null },\n): boolean {\n return !(tier.priceCents > 0) && !tier.stripePriceId;\n}\n\n/**\n * Whether a tier can actually be joined right now.\n *\n * A free tier is always joinable — there is nothing to charge, so Stripe being\n * unconfigured is irrelevant to it. A paid tier needs the group's publishable\n * key, its own Stripe price, and the vault secret; missing any of those drops\n * the tier rather than half-charging for it.\n */\nexport function tierPayable(\n tier: Pick<ChapterTier, \"priceCents\" | \"stripePriceId\">,\n group: TierGroup,\n hasSecretKey: boolean,\n): boolean {\n if (tierIsFree(tier)) return true;\n return Boolean(group.stripePublishableKey && tier.stripePriceId && hasSecretKey);\n}\n\n/** Sort by `sortOrder`, then `id`, so a page never reorders between reads. */\nfunction byOrder(a: ChapterTier, b: ChapterTier): number {\n return a.sortOrder - b.sortOrder || a.id.localeCompare(b.id);\n}\n\n/**\n * The tiers a chapter offers, given the stored rows.\n *\n * A chapter that predates tiers has no rows, and must keep working untouched:\n * one implicit `\"standard\"` tier is synthesized from the group's legacy\n * `standardPriceCents`/`stripePriceId` columns. That is why there is no\n * migration — an existing chapter reads exactly as it did before, and writing\n * its first real tier row takes over.\n */\nexport function resolveTiers(group: TierGroup, rows: readonly ChapterTier[] = []): ChapterTier[] {\n const stored = rows.filter((tier) => tier.active);\n if (stored.length) return [...stored].sort(byOrder);\n return [{\n id: \"standard\",\n groupId: String(group.id ?? \"\"),\n name: \"Membership\",\n priceCents: group.standardPriceCents ?? 0,\n ...(group.stripePriceId ? { stripePriceId: group.stripePriceId } : {}),\n sortOrder: 0,\n active: true,\n }];\n}\n\n/** The tiers to show on the join page: active, and joinable as configured. */\nexport function offerableTiers(\n tiers: readonly ChapterTier[],\n group: TierGroup,\n hasSecretKey: boolean,\n): ChapterTier[] {\n return tiers.filter((tier) => tier.active && tierPayable(tier, group, hasSecretKey));\n}\n\n/**\n * Resolve the tier an application chose.\n *\n * An absent `tierId` is the pre-tier case and selects the only offered tier\n * when exactly one exists; with several it is genuinely ambiguous and returns\n * `null`, because guessing would charge someone the wrong price.\n */\nexport function findTier(\n tiers: readonly ChapterTier[],\n tierId: string | null | undefined,\n): ChapterTier | null {\n if (!tierId) return tiers.length === 1 ? tiers[0]! : null;\n return tiers.find((tier) => tier.id === tierId) ?? null;\n}\n\n/** The public shape of a tier on the join config. Never exposes Stripe ids. */\nexport interface JoinConfigTier {\n id: string;\n name: string;\n priceCents: number;\n blurb: string;\n free: boolean;\n}\n\n/** Project tiers for the public join config, dropping provider identifiers. */\nexport function joinConfigTiers(tiers: readonly ChapterTier[]): JoinConfigTier[] {\n return tiers.map((tier) => ({\n id: tier.id,\n name: tier.name,\n priceCents: tier.priceCents,\n blurb: tier.blurb ?? \"\",\n free: tierIsFree(tier),\n }));\n}\n","import type { MemberPageAudience, MemberPageUpsellOffer } from \"./member-content\";\n\nexport const ID = /^[a-z][a-z0-9-]{0,79}$/;\nexport const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nexport const ROOT_KEYS = new Set([\"schemaVersion\", \"revision\", \"generatedAt\", \"source\", \"target\", \"pages\", \"upsellOverrides\"]);\nexport const SOURCE_KEYS = new Set([\"type\", \"appId\"]);\nexport const TARGET_KEYS = new Set([\"chapterId\", \"environment\"]);\nexport const PAGE_KEYS = new Set([\"id\", \"slug\", \"title\", \"summary\", \"navigation\", \"audience\", \"teaserMarkdown\", \"bodyMarkdown\", \"upsell\"]);\nexport const NAV_KEYS = new Set([\"section\", \"order\", \"parentId\"]);\nexport const AUDIENCE_KEYS = new Set([\"kind\", \"tierIds\"]);\nexport const UPSELL_KEYS = new Set([\"owner\", \"offer\"]);\nexport const OFFER_KEYS = new Set([\"tierId\", \"label\", \"bodyMarkdown\", \"ctaLabel\"]);\nexport const OVERRIDE_KEYS = new Set([\"pageId\", \"offer\"]);\nexport const MAX_PAGES = 100;\nexport const MAX_MARKDOWN = 65_536;\nexport const MAX_TEXT = 240;\n\nexport const record = (value: unknown): Record<string, unknown> | null =>\n value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null;\n\nexport function unknownKeys(value: Record<string, unknown>, allowed: ReadonlySet<string>, path: string, errors: string[]): void {\n for (const key of Object.keys(value)) if (!allowed.has(key)) errors.push(`${path}.${key} is not supported`);\n}\n\nexport function textValue(value: unknown, path: string, errors: string[], max = MAX_TEXT, required = false): string | undefined {\n if (value === undefined) {\n if (required) errors.push(`${path} is required`);\n return undefined;\n }\n if (typeof value !== \"string\") {\n errors.push(`${path} must be a string`);\n return undefined;\n }\n const valueText = value.trim();\n if (required && !valueText) errors.push(`${path} is required`);\n if (valueText.length > max) errors.push(`${path} must be at most ${max.toLocaleString(\"en-US\")} characters`);\n return valueText;\n}\n\nexport function offerValue(\n value: unknown,\n path: string,\n errors: string[],\n tiers: ReadonlySet<string>,\n audience?: MemberPageAudience,\n): MemberPageUpsellOffer | undefined {\n const raw = record(value);\n if (!raw) {\n errors.push(`${path} must be an object`);\n return undefined;\n }\n unknownKeys(raw, OFFER_KEYS, path, errors);\n const tierId = textValue(raw.tierId, `${path}.tierId`, errors, 80, true) ?? \"\";\n if (tierId && !ID.test(tierId)) errors.push(`${path}.tierId must be a lowercase kebab-case id`);\n if (tiers.size && !tiers.has(tierId)) errors.push(`${path}.tierId must reference a declared tier`);\n if (audience?.kind === \"tiers\" && tierId && !audience.tierIds.includes(tierId)) {\n errors.push(`${path}.tierId must grant access to this page`);\n }\n const label = textValue(raw.label, `${path}.label`, errors);\n const bodyMarkdown = textValue(raw.bodyMarkdown, `${path}.bodyMarkdown`, errors, MAX_MARKDOWN);\n const ctaLabel = textValue(raw.ctaLabel, `${path}.ctaLabel`, errors);\n return {\n tierId,\n ...(label ? { label } : {}),\n ...(bodyMarkdown ? { bodyMarkdown } : {}),\n ...(ctaLabel ? { ctaLabel } : {}),\n };\n}\n","import {\n MEMBER_CONTENT_SCHEMA_VERSION,\n type MemberContentDocument,\n type MemberContentPage,\n type MemberContentSource,\n type MemberContentTarget,\n type MemberContentValidationOptions,\n type MemberContentValidationResult,\n type MemberPageAudience,\n type MemberPageNavigation,\n type MemberPageUpsell,\n type MemberPageUpsellOverride,\n} from \"./member-content\";\nimport {\n AUDIENCE_KEYS,\n ID,\n MAX_MARKDOWN,\n MAX_PAGES,\n MAX_TEXT,\n NAV_KEYS,\n OVERRIDE_KEYS,\n PAGE_KEYS,\n ROOT_KEYS,\n SLUG,\n SOURCE_KEYS,\n TARGET_KEYS,\n UPSELL_KEYS,\n offerValue,\n record,\n textValue,\n unknownKeys,\n} from \"./member-content-validation-helpers\";\n\n/** Validate one complete parent or chapter authoring layer with actionable paths. */\nexport function validateMemberContentDocument(\n input: unknown,\n options: MemberContentValidationOptions = {},\n): MemberContentValidationResult {\n const errors: string[] = [];\n const root = record(input);\n if (!root) return { ok: false, errors: [\"document must be an object\"] };\n unknownKeys(root, ROOT_KEYS, \"document\", errors);\n if (root.schemaVersion !== MEMBER_CONTENT_SCHEMA_VERSION) errors.push(\"document.schemaVersion must be 1\");\n if (!Number.isInteger(root.revision) || Number(root.revision) < 1) errors.push(\"document.revision must be a positive integer\");\n if (!Number.isInteger(root.generatedAt) || Number(root.generatedAt) < 0) errors.push(\"document.generatedAt must be a non-negative integer timestamp\");\n\n const sourceRaw = record(root.source);\n let source: MemberContentSource = { type: \"chapter\", appId: \"invalid\" };\n if (!sourceRaw) errors.push(\"document.source must be an object\");\n else {\n unknownKeys(sourceRaw, SOURCE_KEYS, \"document.source\", errors);\n const type = sourceRaw.type;\n const appId = textValue(sourceRaw.appId, \"document.source.appId\", errors, 63, true) ?? \"\";\n if (type !== \"parent\" && type !== \"chapter\") errors.push(\"document.source.type must be parent or chapter\");\n if (appId && !ID.test(appId)) errors.push(\"document.source.appId must be a lowercase app slug\");\n if (options.sourceType && type !== options.sourceType) errors.push(`document.source.type must be ${options.sourceType}`);\n if (options.sourceAppId && appId !== options.sourceAppId) errors.push(`document.source.appId must be ${options.sourceAppId}`);\n if (type === \"parent\" || type === \"chapter\") source = { type, appId };\n }\n\n let target: MemberContentTarget | undefined;\n if (root.target !== undefined) {\n const targetRaw = record(root.target);\n if (!targetRaw) errors.push(\"document.target must be an object\");\n else {\n unknownKeys(targetRaw, TARGET_KEYS, \"document.target\", errors);\n const chapterId = textValue(targetRaw.chapterId, \"document.target.chapterId\", errors, 63, true) ?? \"\";\n const environment = textValue(targetRaw.environment, \"document.target.environment\", errors, 80, true) ?? \"\";\n target = { chapterId, environment };\n }\n }\n if (source.type === \"parent\" && !target) errors.push(\"document.target is required for parent content\");\n if (source.type === \"chapter\" && target) errors.push(\"document.target is not supported for chapter content\");\n\n if (!Array.isArray(root.pages)) errors.push(\"document.pages must be an array\");\n const rawPages = Array.isArray(root.pages) ? root.pages : [];\n if (rawPages.length > MAX_PAGES) errors.push(`document.pages supports at most ${MAX_PAGES} entries`);\n const tierIds = new Set((options.tiers ?? []).map((tier) => tier.id));\n const knownParentIds = new Set((options.parentPages ?? []).map((page) => page.id));\n const ids = new Set<string>();\n const slugs = new Set<string>();\n const pages: MemberContentPage[] = [];\n for (const [index, value] of rawPages.slice(0, MAX_PAGES).entries()) {\n const path = `document.pages[${index}]`;\n const raw = record(value);\n if (!raw) {\n errors.push(`${path} must be an object`);\n continue;\n }\n unknownKeys(raw, PAGE_KEYS, path, errors);\n const id = textValue(raw.id, `${path}.id`, errors, 80, true) ?? \"\";\n const slug = textValue(raw.slug, `${path}.slug`, errors, 120, true) ?? \"\";\n const title = textValue(raw.title, `${path}.title`, errors, MAX_TEXT, true) ?? \"\";\n if (id && !ID.test(id)) errors.push(`${path}.id must be a lowercase kebab-case id`);\n if (slug && !SLUG.test(slug)) errors.push(`${path}.slug must be a lowercase URL slug`);\n if (ids.has(id) || knownParentIds.has(id)) errors.push(`${path}.id duplicates page \"${id}\"`);\n if (slugs.has(slug) || (options.parentPages ?? []).some((page) => page.slug === slug)) errors.push(`${path}.slug duplicates \"${slug}\"`);\n ids.add(id);\n slugs.add(slug);\n\n const navRaw = record(raw.navigation);\n let navigation: MemberPageNavigation = { section: \"General\", order: index };\n if (!navRaw) errors.push(`${path}.navigation must be an object`);\n else {\n unknownKeys(navRaw, NAV_KEYS, `${path}.navigation`, errors);\n const section = textValue(navRaw.section, `${path}.navigation.section`, errors, 120, true) ?? \"\";\n const order = navRaw.order;\n if (!Number.isInteger(order) || Number(order) < 0 || Number(order) > 1_000_000) {\n errors.push(`${path}.navigation.order must be an integer from 0 to 1,000,000`);\n }\n const parentId = textValue(navRaw.parentId, `${path}.navigation.parentId`, errors, 80);\n navigation = { section, order: Number.isInteger(order) ? Number(order) : index, ...(parentId ? { parentId } : {}) };\n }\n\n const audienceRaw = record(raw.audience);\n let audience: MemberPageAudience = { kind: \"all-members\" };\n if (!audienceRaw) errors.push(`${path}.audience must be an object`);\n else {\n unknownKeys(audienceRaw, AUDIENCE_KEYS, `${path}.audience`, errors);\n if (audienceRaw.kind === \"all-members\") {\n if (audienceRaw.tierIds !== undefined) errors.push(`${path}.audience.tierIds is not supported for all-members`);\n } else if (audienceRaw.kind === \"tiers\") {\n if (!Array.isArray(audienceRaw.tierIds) || audienceRaw.tierIds.length === 0) {\n errors.push(`${path}.audience.tierIds must be a non-empty array`);\n }\n const values = Array.isArray(audienceRaw.tierIds) ? audienceRaw.tierIds : [];\n const normalized: string[] = [];\n for (const [tierIndex, value] of values.entries()) {\n const tier = textValue(value, `${path}.audience.tierIds[${tierIndex}]`, errors, 80, true) ?? \"\";\n if (normalized.includes(tier)) errors.push(`${path}.audience.tierIds duplicates \"${tier}\"`);\n if (tierIds.size && !tierIds.has(tier)) errors.push(`${path}.audience.tierIds references undeclared tier \"${tier}\"`);\n normalized.push(tier);\n }\n audience = { kind: \"tiers\", tierIds: normalized };\n } else errors.push(`${path}.audience.kind must be all-members or tiers`);\n }\n\n const summary = textValue(raw.summary, `${path}.summary`, errors, 2_000);\n const teaserMarkdown = textValue(raw.teaserMarkdown, `${path}.teaserMarkdown`, errors, MAX_MARKDOWN);\n const bodyMarkdown = textValue(raw.bodyMarkdown, `${path}.bodyMarkdown`, errors, MAX_MARKDOWN, true) ?? \"\";\n let upsell: MemberPageUpsell | undefined;\n if (raw.upsell !== undefined) {\n const upsellRaw = record(raw.upsell);\n if (!upsellRaw) errors.push(`${path}.upsell must be an object`);\n else {\n unknownKeys(upsellRaw, UPSELL_KEYS, `${path}.upsell`, errors);\n const owner = upsellRaw.owner;\n if (owner !== \"parent\" && owner !== \"chapter\") errors.push(`${path}.upsell.owner must be parent or chapter`);\n if (source.type === \"chapter\" && owner === \"parent\") errors.push(`${path}.upsell.owner cannot be parent on a chapter page`);\n if (source.type === \"parent\" && owner === \"parent\" && upsellRaw.offer === undefined) errors.push(`${path}.upsell.offer is required when the parent owns the offer`);\n if (source.type === \"parent\" && owner === \"chapter\" && upsellRaw.offer !== undefined) errors.push(`${path}.upsell.offer must be set by the chapter after delegation`);\n const offer = upsellRaw.offer === undefined ? undefined : offerValue(upsellRaw.offer, `${path}.upsell.offer`, errors, tierIds, audience);\n if (owner === \"parent\") upsell = { owner, offer: offer ?? { tierId: \"\" } };\n else if (owner === \"chapter\") upsell = { owner, ...(offer ? { offer } : {}) };\n }\n }\n pages.push({ id, slug, title, ...(summary ? { summary } : {}), navigation, audience, ...(teaserMarkdown ? { teaserMarkdown } : {}), bodyMarkdown, ...(upsell ? { upsell } : {}) });\n }\n\n const allIds = new Set([...knownParentIds, ...ids]);\n for (const [index, page] of pages.entries()) {\n const parentId = page.navigation.parentId;\n if (parentId && !allIds.has(parentId)) errors.push(`document.pages[${index}].navigation.parentId references unknown page \"${parentId}\"`);\n if (parentId === page.id) errors.push(`document.pages[${index}].navigation.parentId cannot reference itself`);\n }\n for (const page of pages) {\n const seen = new Set([page.id]);\n let parentId = page.navigation.parentId;\n while (parentId) {\n if (seen.has(parentId)) {\n errors.push(`document.pages contains a navigation cycle at \"${page.id}\"`);\n break;\n }\n seen.add(parentId);\n parentId = pages.find((candidate) => candidate.id === parentId)?.navigation.parentId;\n }\n }\n\n let upsellOverrides: MemberPageUpsellOverride[] | undefined;\n if (root.upsellOverrides !== undefined) {\n if (source.type !== \"chapter\") errors.push(\"document.upsellOverrides is supported only for chapter content\");\n if (!Array.isArray(root.upsellOverrides)) errors.push(\"document.upsellOverrides must be an array\");\n const values = Array.isArray(root.upsellOverrides) ? root.upsellOverrides : [];\n const seen = new Set<string>();\n upsellOverrides = [];\n for (const [index, value] of values.entries()) {\n const path = `document.upsellOverrides[${index}]`;\n const raw = record(value);\n if (!raw) {\n errors.push(`${path} must be an object`);\n continue;\n }\n unknownKeys(raw, OVERRIDE_KEYS, path, errors);\n const pageId = textValue(raw.pageId, `${path}.pageId`, errors, 80, true) ?? \"\";\n if (seen.has(pageId)) errors.push(`${path}.pageId duplicates \"${pageId}\"`);\n seen.add(pageId);\n const parentPage = (options.parentPages ?? []).find((page) => page.id === pageId);\n if (!parentPage) errors.push(`${path}.pageId must reference a parent page`);\n else if (parentPage.upsell?.owner !== \"chapter\") errors.push(`${path}.pageId does not delegate upsell authority to the chapter`);\n const offer = offerValue(raw.offer, `${path}.offer`, errors, tierIds, parentPage?.audience);\n if (offer) upsellOverrides.push({ pageId, offer });\n }\n }\n if (errors.length) return { ok: false, errors };\n return { ok: true, value: {\n schemaVersion: MEMBER_CONTENT_SCHEMA_VERSION,\n revision: Number(root.revision),\n generatedAt: Number(root.generatedAt),\n source,\n ...(target ? { target } : {}),\n pages,\n ...(upsellOverrides ? { upsellOverrides } : {}),\n } };\n}\n\n/** Validate or fail closed with every actionable document error. */\nexport function memberContentDocument(input: unknown, options: MemberContentValidationOptions = {}): MemberContentDocument {\n const result = validateMemberContentDocument(input, options);\n if (!result.ok) throw new TypeError(`Invalid member content document: ${result.errors.join(\"; \")}`);\n return result.value;\n}\n","/** Versioned contract for authenticated member content. */\nexport const MEMBER_CONTENT_SCHEMA_VERSION = 1 as const;\n/** Authenticated member projection endpoint. */\nexport const MEMBER_CONTENT_PATH = \"/api/member-content\" as const;\n/** Dedicated signed Parent → Chapter content-delivery endpoint. */\nexport const MEMBER_CONTENT_CONTROL_PATH = \"/api/member-content-control\" as const;\n\n/** Authority that authored one independently stored member-content layer. */\nexport type MemberContentSourceType = \"parent\" | \"chapter\";\n/** Stable author identity attached to every member-content document and page. */\nexport interface MemberContentSource { type: MemberContentSourceType; appId: string }\n/** Chapter deployment that a parent member-content revision is intended for. */\nexport interface MemberContentTarget { chapterId: string; environment: string }\n\n/** Navigation is data, so agents do not have to coordinate route code. */\nexport interface MemberPageNavigation {\n section: string;\n order: number;\n parentId?: string;\n}\n\n/** Explicit sets avoid unsafe assumptions that commercial tiers form a ladder. */\nexport type MemberPageAudience =\n | { kind: \"all-members\" }\n | { kind: \"tiers\"; tierIds: readonly string[] };\n\n/** Authored offer copy. Price and provider identity deliberately do not live here. */\nexport interface MemberPageUpsellOffer {\n tierId: string;\n label?: string;\n bodyMarkdown?: string;\n ctaLabel?: string;\n}\n\n/** Parent offer authority is explicit; a Chapter can edit only a delegated offer. */\nexport type MemberPageUpsell =\n | { owner: \"parent\"; offer: MemberPageUpsellOffer }\n | { owner: \"chapter\"; offer?: MemberPageUpsellOffer };\n\n/** Authored member page whose body is disclosed only after server-side projection. */\nexport interface MemberContentPage {\n id: string;\n slug: string;\n title: string;\n summary?: string;\n navigation: MemberPageNavigation;\n audience: MemberPageAudience;\n /** Safe Markdown shown while the body is withheld. */\n teaserMarkdown?: string;\n /** Never serialized to a viewer whose audience does not match. */\n bodyMarkdown: string;\n upsell?: MemberPageUpsell;\n}\n\n/** Chapter-owned offer attached to a Parent page that delegated offer authority. */\nexport interface MemberPageUpsellOverride { pageId: string; offer: MemberPageUpsellOffer }\n\n/** One complete source layer. Parent and Chapter layers are stored independently. */\nexport interface MemberContentDocument {\n schemaVersion: typeof MEMBER_CONTENT_SCHEMA_VERSION;\n revision: number;\n generatedAt: number;\n source: MemberContentSource;\n target?: MemberContentTarget;\n pages: readonly MemberContentPage[];\n upsellOverrides?: readonly MemberPageUpsellOverride[];\n}\n\n/** Provider-neutral tier facts used to validate access and resolve safe offers. */\nexport interface MemberContentTierAuthority {\n id: string;\n name?: string;\n priceCents?: number;\n active?: boolean;\n}\n\n/** Local authority supplied while validating a member-content document. */\nexport interface MemberContentValidationOptions {\n sourceType?: MemberContentSourceType;\n sourceAppId?: string;\n tiers?: readonly MemberContentTierAuthority[];\n parentPages?: readonly MemberContentPage[];\n}\n\n/** Validated document or an actionable collection of contract errors. */\nexport type MemberContentValidationResult =\n | { ok: true; value: MemberContentDocument }\n | { ok: false; errors: readonly string[] };\n\n/** Composed member page retaining the identity of its authoring layer. */\nexport interface EffectiveMemberContentPage extends MemberContentPage { source: MemberContentSource }\n/** Deterministically ordered parent and chapter layers with their source revisions. */\nexport interface EffectiveMemberContent {\n pages: readonly EffectiveMemberContentPage[];\n parentRevision: number | null;\n chapterRevision: number | null;\n}\n/** Server-authoritative identity facts used for member-content disclosure. */\nexport interface MemberContentViewer { tierId: string | null; admin: boolean }\n/** Authored upsell joined to active chapter tier name and price authority. */\nexport interface ResolvedMemberPageUpsell extends MemberPageUpsellOffer { tierName: string; priceCents: number }\n\n/** Viewer-safe page result; locked projections never carry bodyMarkdown. */\nexport interface MemberContentPageProjection {\n id: string;\n slug: string;\n title: string;\n summary?: string;\n navigation: MemberPageNavigation;\n audience: MemberPageAudience;\n source: MemberContentSource;\n access: \"allowed\" | \"locked\";\n teaserMarkdown?: string;\n bodyMarkdown?: string;\n upsell?: ResolvedMemberPageUpsell;\n}\n\n/** Complete viewer-safe member navigation and revision projection. */\nexport interface MemberContentProjection {\n pages: readonly MemberContentPageProjection[];\n viewer: { tierId: string | null; admin: boolean };\n revisions: { parent: number | null; chapter: number | null };\n}\n\n/** Canonical parent document and digest transmitted over the signed control edge. */\nexport interface MemberContentEnvelope { digest: string; document: MemberContentDocument }\n/** Durable Chapter acknowledgement for an accepted or idempotently replayed revision. */\nexport interface MemberContentReceipt {\n ok: true;\n target: MemberContentTarget;\n revision: number;\n digest: string;\n status: \"accepted\" | \"replayed\";\n acknowledgedAt: number;\n}\n\n/** Stable rejection reasons returned by the signed member-content control endpoint. */\nexport type MemberContentRejection =\n | \"invalid_document\"\n | \"invalid_digest\"\n | \"wrong_source\"\n | \"wrong_target\"\n | \"wrong_environment\"\n | \"stale_revision\"\n | \"conflicting_revision\"\n | \"materialization_failed\";\n\nexport { memberContentDocument, validateMemberContentDocument } from \"./member-content-validation\";\n\nconst pageOrder = (a: EffectiveMemberContentPage, b: EffectiveMemberContentPage): number =>\n a.navigation.section.localeCompare(b.navigation.section)\n || a.navigation.order - b.navigation.order\n || a.title.localeCompare(b.title)\n || a.id.localeCompare(b.id);\n\n/** Compose immutable Parent content with independently stored Chapter content. */\nexport function composeMemberContent(\n parent: MemberContentDocument | null | undefined,\n chapter: MemberContentDocument | null | undefined,\n): EffectiveMemberContent {\n const pages: EffectiveMemberContentPage[] = [];\n const parentPages = new Map<string, EffectiveMemberContentPage>();\n for (const page of parent?.pages ?? []) {\n const effective = { ...page, source: parent!.source };\n parentPages.set(page.id, effective);\n pages.push(effective);\n }\n for (const override of chapter?.upsellOverrides ?? []) {\n const page = parentPages.get(override.pageId);\n if (page?.upsell?.owner === \"chapter\") page.upsell = { owner: \"chapter\", offer: override.offer };\n }\n for (const page of chapter?.pages ?? []) {\n if (parentPages.has(page.id) || pages.some((candidate) => candidate.slug === page.slug)) {\n throw new TypeError(`Chapter member page \"${page.id}\" conflicts with parent content`);\n }\n pages.push({ ...page, source: chapter!.source });\n }\n return {\n pages: pages.sort(pageOrder),\n parentRevision: parent?.revision ?? null,\n chapterRevision: chapter?.revision ?? null,\n };\n}\n\nconst allowed = (page: MemberContentPage, viewer: MemberContentViewer): boolean =>\n viewer.admin\n || page.audience.kind === \"all-members\"\n || (viewer.tierId !== null && page.audience.tierIds.includes(viewer.tierId));\n\n/** Restricted bodies are omitted and authored offers are joined to live tier authority. */\nexport function projectMemberContent(\n content: EffectiveMemberContent,\n viewer: MemberContentViewer,\n tiers: readonly MemberContentTierAuthority[],\n): MemberContentProjection {\n const authority = new Map(tiers.filter((tier) => tier.active !== false).map((tier) => [tier.id, tier]));\n return {\n viewer: { ...viewer },\n revisions: { parent: content.parentRevision, chapter: content.chapterRevision },\n pages: content.pages.map((page) => {\n const canRead = allowed(page, viewer);\n const offer = !canRead ? page.upsell?.offer : undefined;\n const tier = offer ? authority.get(offer.tierId) : undefined;\n const upsell = offer && tier && typeof tier.name === \"string\" && typeof tier.priceCents === \"number\"\n ? { ...offer, tierName: tier.name, priceCents: tier.priceCents }\n : undefined;\n return {\n id: page.id,\n slug: page.slug,\n title: page.title,\n ...(page.summary ? { summary: page.summary } : {}),\n navigation: page.navigation,\n audience: page.audience,\n source: page.source,\n access: canRead ? \"allowed\" as const : \"locked\" as const,\n ...(page.teaserMarkdown ? { teaserMarkdown: page.teaserMarkdown } : {}),\n ...(canRead ? { bodyMarkdown: page.bodyMarkdown } : {}),\n ...(upsell ? { upsell } : {}),\n };\n }),\n };\n}\n","const encoder = new TextEncoder();\n\nfunction canonicalValue(value: unknown): string {\n if (value === null || typeof value === \"boolean\" || typeof value === \"number\" || typeof value === \"string\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) return `[${value.map(canonicalValue).join(\",\")}]`;\n if (typeof value !== \"object\") throw new TypeError(\"member content contains an unsupported value\");\n const record = value as Record<string, unknown>;\n const entries = Object.keys(record).sort().flatMap((key) => {\n const item = record[key];\n return item === undefined ? [] : [`${JSON.stringify(key)}:${canonicalValue(item)}`];\n });\n return `{${entries.join(\",\")}}`;\n}\n\n/** Serialize JSON-like member content with recursively sorted object keys. */\nexport function canonicalMemberContent(value: unknown): string {\n return canonicalValue(value);\n}\n\n/** Compute the canonical SHA-256 digest for one Parent content revision. */\nexport async function memberContentDigest(document: unknown): Promise<string> {\n const digest = await crypto.subtle.digest(\"SHA-256\", encoder.encode(canonicalMemberContent(document)));\n return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\n/** Pair one content document with the exact digest the follower acknowledges. */\nexport async function createMemberContentEnvelope(document: import(\"./member-content\").MemberContentDocument) {\n return { document, digest: await memberContentDigest(document) };\n}\n","// The chapter email pipeline: exactly-once delivery, a non-production fail-safe,\n// and template rendering. Every property here is easy to get wrong and expensive\n// to get wrong, so the correctness-critical decisions — the dedupe check (E1),\n// the dev-redirect / log-only fail-safe (E2), and template rendering (E4) — are\n// PURE and fully tested in this module. The worker supplies the transport +\n// odla-db and performs the actual send + emailLog write around these decisions.\n//\n// Chapter's operational templates ({ subject, text, enabled? }) are\n// transactional lifecycle mail by construction — a site owner edits the copy in\n// Settings but cannot reclassify one as marketing. Consent-gated marketing blasts\n// go through @odla-ai/crm, which owns the transactional-vs-marketing template\n// class as code (E3), so relabeling copy can never bypass the consent gate.\n\n/** One owner-editable template row on the group. `enabled` absent = enabled. */\nexport interface EmailTemplateRow {\n subject: string;\n text: string;\n enabled?: boolean;\n}\n\n/** The `groups`-row fields the email pipeline reads. */\nexport interface EmailGroup {\n id: string;\n name: string;\n replyTo: string;\n /** Non-prod debug inbox: all mail redirects here outside prod (E2). */\n debugEmail?: string;\n refundPolicyText?: string;\n commitmentText?: string;\n normsText?: string;\n emailTemplates: Record<string, EmailTemplateRow>;\n}\n\n/** `{{placeholder}}` substitution; unknown placeholders render empty. */\nexport function render(template: string, vars: Record<string, string>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => vars[key] ?? \"\");\n}\n\n/** Group-level vars every template receives, under the caller's vars. */\nfunction groupVars(group: EmailGroup, vars: Record<string, string>): Record<string, string> {\n return {\n ...vars,\n refundPolicyText: group.refundPolicyText ?? \"\",\n commitmentText: group.commitmentText ?? \"\",\n normsText: group.normsText ?? \"\",\n };\n}\n\n/**\n * Re-render a template's body for history/preview (E4): the CRM comms history\n * reads back emails whose body predates `emailLog.body` by rendering the current\n * template with the recipient's vars. Same substitution + group vars as the send\n * path. `null` for an unknown template. Reflects the copy as it reads today, not\n * necessarily the exact bytes originally sent (only `emailLog.body` is byte-exact).\n */\nexport function renderTemplateBody(group: EmailGroup, template: string, vars: Record<string, string>): string | null {\n const tpl = group.emailTemplates?.[template];\n if (!tpl) return null;\n return render(tpl.text, groupVars(group, vars));\n}\n\n/**\n * E1 (exactly-once): given the prior `emailLog` rows for a `dedupeKey`, has the\n * mail already been delivered? A prior row with **no error** means yes — the\n * caller short-circuits the resend. Failure rows (which carry an `error` and are\n * written without the dedupe mutationId) do not count, so a retry after a failure\n * can still succeed.\n */\nexport function isAlreadySent(priorRows: ReadonlyArray<{ error?: unknown }>): boolean {\n return priorRows.some((row) => !row.error);\n}\n\n/** The pure delivery decision produced by {@link planDelivery}. */\nexport type DeliveryDecision =\n | { deliver: false; reason: \"template-missing\" | \"disabled\" }\n | {\n deliver: true;\n /** Which transport to use — `log-only` records the send but delivers nothing. */\n transport: \"cloudflare\" | \"log-only\";\n to: string;\n subject: string;\n text: string;\n /** True when redirected to the non-prod debug inbox. */\n redirected: boolean;\n };\n\n/**\n * The pure delivery decision (E2 fail-safe + E3 enabled). Given the env, group,\n * template, recipient, and whether a real Cloudflare transport is wired:\n * - missing template → not delivered (`template-missing`);\n * - disabled template and not forced → not delivered (`disabled`);\n * - **non-prod with a debug inbox** → REDIRECT to it, `\"[dev] \"` subject prefix,\n * a dev-redirect note in the body, so test applicants never receive real mail;\n * - **non-prod with NO debug inbox** → force `log-only` (deliver nothing) — the\n * fail-safe that protects every site's test data;\n * - prod → deliver via the real transport (`cloudflare` if wired, else `log-only`).\n */\nexport function planDelivery(input: {\n envName: string;\n group: EmailGroup;\n template: string;\n to: string;\n vars: Record<string, string>;\n /** Whether a Cloudflare Email Service transport (binding + verified from) is wired. */\n cloudflareReady: boolean;\n /** The admin test route may send a disabled template. */\n force?: boolean;\n}): DeliveryDecision {\n const tpl = input.group.emailTemplates?.[input.template];\n if (!tpl) return { deliver: false, reason: \"template-missing\" };\n if (tpl.enabled === false && !input.force) return { deliver: false, reason: \"disabled\" };\n\n const vars = groupVars(input.group, input.vars);\n const isProd = input.envName === \"prod\";\n const redirect = !isProd && !!input.group.debugEmail;\n const transport: \"cloudflare\" | \"log-only\" =\n !isProd && !redirect ? \"log-only\" : input.cloudflareReady ? \"cloudflare\" : \"log-only\";\n const to = redirect ? (input.group.debugEmail as string) : input.to;\n const subject = (redirect ? \"[dev] \" : \"\") + render(tpl.subject, vars);\n const text = redirect\n ? `(dev redirect; original recipient: ${input.to})\\n\\n` + render(tpl.text, vars)\n : render(tpl.text, vars);\n return { deliver: true, transport, to, subject, text, redirected: redirect };\n}\n","// sendTemplated — the operational-email orchestration that wires the pure email\n// decisions (./email: isAlreadySent E1, planDelivery E2/E3) to odla-db + a\n// transport. Structural (takes a ChapterDb + a sender), so it's FakeDb-testable\n// like submitApplication/projectSharedRecord. The worker's lifecycle routes call\n// it to send the prep / payment-confirmation / admin-alert mail.\n//\n// Exactly-once is enforced twice: a prior successful emailLog row short-circuits\n// the resend (query + isAlreadySent), AND the success row is written under the\n// `email:${dedupeKey}` mutationId so a racing double-send dedupes at the db layer.\n// Failure rows omit the mutationId, so a retry after a transient failure can send.\nimport { isAlreadySent, planDelivery } from \"./email\";\nimport type { EmailGroup } from \"./email\";\nimport type { ChapterDb } from \"./types\";\n\n/** The canonical lifecycle email templates chapter fires, in send-order. Owner-\n * editable copy lives on the group row; this is the fixed set the admin email\n * editor + test route iterate. */\nexport const EMAIL_TEMPLATE_NAMES = [\"adminNotification\", \"paymentConfirmation\", \"prepEmail\", \"onboardingInvite\"] as const;\n\n/** One of {@link EMAIL_TEMPLATE_NAMES}. */\nexport type EmailTemplateName = (typeof EMAIL_TEMPLATE_NAMES)[number];\n\n/** The mail transport (the worker's Cloudflare SEND_EMAIL binding). */\nexport interface MailSender {\n send(payload: { from: string; to: string[]; subject: string; text?: string; replyTo?: string }): Promise<{ messageId: string }>;\n}\n\n/** Deps for {@link sendTemplated} — the db, the env name (drives the fail-safe),\n * the transport + from (absent ⇒ log-only), and injected clock/id. */\nexport interface NotifyDeps {\n db: ChapterDb;\n envName: string;\n sender?: MailSender;\n from?: string;\n now: () => number;\n newId: () => string;\n}\n\n/** One templated send. `dedupeKey` is the exactly-once key. */\nexport interface NotifyInput {\n group: EmailGroup;\n template: string;\n to: string;\n vars: Record<string, string>;\n dedupeKey: string;\n applicationId?: string;\n /** The admin test route may send a disabled template. */\n force?: boolean;\n}\n\n/** The outcome. `sent:true` includes the already-sent short-circuit. */\nexport interface NotifyResult {\n sent: boolean;\n reason?: string;\n}\n\n/**\n * Send a templated lifecycle email exactly once. Short-circuits on a prior\n * successful send; otherwise plans delivery (dev fail-safe applies), sends via the\n * transport when one is wired and the plan calls for it, and records an emailLog\n * row either way (success keyed for exactly-once, failure unkeyed for retry).\n */\nexport async function sendTemplated(deps: NotifyDeps, input: NotifyInput): Promise<NotifyResult> {\n const { emailLog } = await deps.db.query({ emailLog: { $: { where: { dedupeKey: input.dedupeKey } } } });\n const prior = (Array.isArray(emailLog) ? emailLog : []) as Array<{ error?: unknown }>;\n if (isAlreadySent(prior)) return { sent: true, reason: \"already-sent\" };\n\n const cloudflareReady = Boolean(deps.sender && deps.from);\n const decision = planDelivery({\n envName: deps.envName,\n group: input.group,\n template: input.template,\n to: input.to,\n vars: input.vars,\n cloudflareReady,\n force: input.force,\n });\n if (!decision.deliver) return { sent: false, reason: decision.reason };\n\n let error: string | undefined;\n let messageId: string | undefined;\n if (decision.transport === \"cloudflare\" && deps.sender && deps.from) {\n try {\n const res = await deps.sender.send({\n from: deps.from,\n to: [decision.to],\n subject: decision.subject,\n text: decision.text,\n replyTo: input.group.replyTo,\n });\n messageId = res.messageId;\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n }\n }\n\n const id = deps.newId();\n const row: Record<string, unknown> = {\n id,\n groupId: input.group.id,\n to: decision.to,\n template: input.template,\n subject: decision.subject,\n body: decision.text,\n transport: decision.transport,\n redirected: decision.redirected,\n dedupeKey: input.dedupeKey,\n sentAt: deps.now(),\n ...(input.applicationId ? { applicationId: input.applicationId } : {}),\n ...(messageId ? { messageId } : {}),\n ...(error ? { error } : {}),\n };\n await deps.db.transact([{ t: \"update\", ns: \"emailLog\", id, attrs: row }], error ? undefined : { mutationId: `email:${input.dedupeKey}` });\n return error ? { sent: false, reason: error } : { sent: true };\n}\n\n/** Project a `groups` row into the {@link EmailGroup} the email pipeline reads. */\nexport function emailGroupFrom(row: Record<string, unknown>): EmailGroup {\n const str = (v: unknown): string | undefined => (typeof v === \"string\" ? v : undefined);\n const templates = row.emailTemplates && typeof row.emailTemplates === \"object\" ? row.emailTemplates : {};\n return {\n id: String(row.id),\n name: String(row.name ?? \"\"),\n replyTo: str(row.replyTo) ?? \"\",\n debugEmail: str(row.debugEmail),\n refundPolicyText: str(row.refundPolicyText),\n commitmentText: str(row.commitmentText),\n normsText: str(row.normsText),\n emailTemplates: templates as EmailGroup[\"emailTemplates\"],\n };\n}\n","// Payments primitives. Generic Stripe form encoding and webhook authenticity\n// live in @odla-ai/stripe; Chapter keeps only membership-specific readiness,\n// event normalization, and write sets. This preserves Chapter's public exports\n// while making the provider plumbing reusable by every app.\nexport { stripeForm, verifyStripeSignature } from \"@odla-ai/stripe\";\n\n// ── readiness + Stripe wire helpers ──\n\n/** A group row's payment configuration, as far as readiness cares. */\nexport interface PaymentsGroup {\n stripePublishableKey?: string | null;\n stripePriceId?: string | null;\n}\n\n/** Whether a group can take payment: a publishable key + a price id (both on the\n * group row) AND a secret key (the vault). Anything missing drops the join\n * flow's payment step (paymentsReady:false) rather than half-charging. */\nexport function paymentsReady(group: PaymentsGroup, hasSecretKey: boolean): boolean {\n return Boolean(group.stripePublishableKey && group.stripePriceId && hasSecretKey);\n}\n\n/** The Stripe idempotency key for creating an application's subscription — one\n * per application, so a client retry can't orphan a second subscription. */\nexport function subscriptionIdempotencyKey(applicationId: string): string {\n return `sub:${applicationId}`;\n}\n\n/** The db mutationId for a webhook-driven write — exactly-once per Stripe event,\n * so replays are deduped at the db layer. */\nexport function webhookMutationId(eventId: string): string {\n return `stripe:${eventId}`;\n}\n\n// ── webhook normalization (pure; the worker owns the db lookup + writes) ──\n\n/** A raw Stripe event, as far as normalization cares. */\nexport interface StripeEvent {\n id: string;\n type: string;\n data?: { object?: Record<string, unknown> };\n}\n\n/** A normalized, provider-agnostic webhook event. `kind` drives the db write;\n * the application is resolved from `applicationId` (metadata) or `customerId`. */\nexport type WebhookEvent =\n | { kind: \"gift_paid\"; giftIntentId: string; providerObjectId: string }\n | { kind: \"gift_revoked\"; giftIntentId: string; reason: \"refunded\" | \"canceled\" }\n | { kind: \"first_payment\"; applicationId?: string; customerId?: string; renewalAt?: number }\n | { kind: \"renewal\"; applicationId?: string; customerId?: string; renewalAt?: number }\n | { kind: \"refunded\"; applicationId?: string; customerId?: string }\n | { kind: \"canceled\"; applicationId?: string; customerId?: string }\n | { kind: \"ignored\"; type: string };\n\n/** Resolve the application reference on a Stripe object: `applicationId` from\n * metadata (direct, then subscription_details, then nested\n * parent.subscription_details), plus the customer id for the db fallback. */\nexport function findApplicationRef(obj: Record<string, unknown>): { applicationId?: string; customerId?: string } {\n const metaOf = (v: unknown): Record<string, unknown> =>\n v && typeof v === \"object\" ? ((v as Record<string, unknown>).metadata as Record<string, unknown>) ?? {} : {};\n const pick = (m: Record<string, unknown>): string | undefined =>\n typeof m.applicationId === \"string\" ? m.applicationId : undefined;\n const applicationId =\n pick(metaOf(obj)) ?? pick(metaOf(obj.subscription_details)) ?? pick(metaOf((obj.parent as Record<string, unknown> | undefined)?.subscription_details));\n const customerId = typeof obj.customer === \"string\" ? obj.customer : undefined;\n return { ...(applicationId ? { applicationId } : {}), ...(customerId ? { customerId } : {}) };\n}\n\n/** Resolve gift purchase metadata from direct or invoice subscription metadata. */\nexport function findGiftRef(obj: Record<string, unknown>): { giftIntentId?: string; providerObjectId: string } {\n const metaOf = (value: unknown): Record<string, unknown> =>\n value && typeof value === \"object\" ? ((value as Record<string, unknown>).metadata as Record<string, unknown>) ?? {} : {};\n const pick = (metadata: Record<string, unknown>): string | undefined =>\n typeof metadata.giftIntentId === \"string\" ? metadata.giftIntentId : undefined;\n const parent = obj.parent as Record<string, unknown> | undefined;\n const subscription = obj.subscription_details ?? parent?.subscription_details;\n const giftIntentId = pick(metaOf(obj)) ?? pick(metaOf(subscription));\n const subscriptionId = typeof obj.subscription === \"string\"\n ? obj.subscription\n : typeof (subscription as Record<string, unknown> | undefined)?.subscription === \"string\"\n ? String((subscription as Record<string, unknown>).subscription)\n : undefined;\n return { ...(giftIntentId ? { giftIntentId } : {}), providerObjectId: subscriptionId ?? String(obj.id ?? \"\") };\n}\n\n/** Normalize a verified Stripe event into a {@link WebhookEvent}. `invoice.paid`\n * splits into first_payment vs renewal by `billing_reason`; refunds and\n * cancellations map directly; everything else is ignored (acked, not retried). */\nexport function normalizeWebhookEvent(event: StripeEvent): WebhookEvent {\n const obj = event.data?.object ?? {};\n const gift = findGiftRef(obj);\n if (gift.giftIntentId) {\n if (event.type === \"payment_intent.succeeded\" ||\n (event.type === \"invoice.paid\" && obj.billing_reason === \"subscription_create\")) {\n return { kind: \"gift_paid\", giftIntentId: gift.giftIntentId, providerObjectId: gift.providerObjectId };\n }\n if (event.type === \"charge.refunded\") return { kind: \"gift_revoked\", giftIntentId: gift.giftIntentId, reason: \"refunded\" };\n if (event.type === \"customer.subscription.deleted\") return { kind: \"gift_revoked\", giftIntentId: gift.giftIntentId, reason: \"canceled\" };\n return { kind: \"ignored\", type: event.type };\n }\n const ref = findApplicationRef(obj);\n switch (event.type) {\n case \"invoice.paid\": {\n const lines = ((obj.lines as Record<string, unknown> | undefined)?.data as Array<Record<string, unknown>> | undefined) ?? [];\n const periodEnd = (lines[0]?.period as Record<string, unknown> | undefined)?.end;\n const renewalAt = typeof periodEnd === \"number\" ? periodEnd * 1000 : undefined;\n const kind = obj.billing_reason === \"subscription_create\" ? \"first_payment\" : \"renewal\";\n return { kind, ...ref, ...(renewalAt !== undefined ? { renewalAt } : {}) };\n }\n case \"charge.refunded\":\n return { kind: \"refunded\", ...ref };\n case \"customer.subscription.deleted\":\n return { kind: \"canceled\", ...ref };\n default:\n return { kind: \"ignored\", type: event.type };\n }\n}\n\n// ── webhook write-set builders (the authoritative writers of paid/refunded) ──\n\n/** First-payment patch: advance submitted→paid_pending_vetting (never any other\n * transition) and record the renewal date. Empty when nothing changed, so the\n * caller can skip the write. */\nexport function firstPaymentPatch(currentStatus: string, renewalAt?: number): { status?: \"paid_pending_vetting\"; renewalAt?: number } {\n return {\n ...(currentStatus === \"submitted\" ? { status: \"paid_pending_vetting\" as const } : {}),\n ...(renewalAt !== undefined ? { renewalAt } : {}),\n };\n}\n\n/** Renewal-invoice patch: just the new renewal date. */\nexport function renewalPatch(renewalAt: number): { renewalAt: number } {\n return { renewalAt };\n}\n\n/** Refund patch — the SOLE writer of status \"refunded\" (the admin refund route\n * issues the Stripe refund but never sets this; the webhook does). */\nexport function refundedPatch(): { status: \"refunded\" } {\n return { status: \"refunded\" };\n}\n\n/** Subscription-cancellation patch. */\nexport function canceledPatch(): { canceled: true } {\n return { canceled: true };\n}\n","/** Current wire version for parent-authored admission decisions. */\nexport const ADMISSION_GRANTS_SCHEMA_VERSION = 1 as const;\n/** Dedicated signed Parent → Chapter delivery endpoint. */\nexport const ADMISSION_GRANTS_PATH = \"/api/admission-grants\" as const;\n\n/** Whether an exact email can skip or must retain the Chapter interview. */\nexport type AdmissionDecision = \"waive_interview\" | \"require_interview\";\n\n/** One bounded admission decision. Email is PII and never enters public config. */\nexport interface AdmissionGrantInput {\n id: string;\n email: string;\n decision: AdmissionDecision;\n note?: string;\n expiresAt?: number;\n}\n\n/** Complete desired Parent state for one Chapter and environment. */\nexport interface AdmissionGrantDocument {\n schemaVersion: typeof ADMISSION_GRANTS_SCHEMA_VERSION;\n revision: number;\n generatedAt: number;\n source: { appId: string; actor: string };\n target: { chapterId: string; environment: string };\n grants: readonly AdmissionGrantInput[];\n}\n\n/** Canonical desired-state document paired with its integrity digest. */\nexport interface AdmissionGrantEnvelope {\n digest: string;\n document: AdmissionGrantDocument;\n}\n\n/** Chapter acknowledgement for an accepted or idempotently replayed revision. */\nexport interface AdmissionGrantReceipt {\n ok: true;\n target: { chapterId: string; environment: string };\n revision: number;\n digest: string;\n status: \"accepted\" | \"replayed\";\n acknowledgedAt: number;\n}\n\n/** Stable machine-readable rejection reasons returned by a Chapter receiver. */\nexport type AdmissionGrantRejection =\n | \"invalid_document\"\n | \"invalid_digest\"\n | \"wrong_source\"\n | \"wrong_target\"\n | \"wrong_environment\"\n | \"stale_revision\"\n | \"conflicting_revision\"\n | \"materialization_failed\";\n","const encoder = new TextEncoder();\n\nfunction canonicalValue(value: unknown): string {\n if (value === null || typeof value === \"boolean\" || typeof value === \"number\" || typeof value === \"string\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) return `[${value.map(canonicalValue).join(\",\")}]`;\n if (typeof value !== \"object\") throw new TypeError(\"signup control contains an unsupported value\");\n const record = value as Record<string, unknown>;\n const entries = Object.keys(record).sort().flatMap((key) => {\n const item = record[key];\n return item === undefined ? [] : [`${JSON.stringify(key)}:${canonicalValue(item)}`];\n });\n return `{${entries.join(\",\")}}`;\n}\n\n/** Serialize JSON-like signup state with recursively sorted object keys. */\nexport function canonicalSignupControl(value: unknown): string {\n return canonicalValue(value);\n}\n\n/** Compute the protocol's canonical SHA-256 digest for desired signup state. */\nexport async function signupControlDigest(document: unknown): Promise<string> {\n const digest = await crypto.subtle.digest(\"SHA-256\", encoder.encode(canonicalSignupControl(document)));\n return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\n/** Pair one desired-state document with its canonical digest for delivery. */\nexport async function createSignupControlEnvelope(document: import(\"./signup-control-contract\").SignupControlDocument) {\n return { document, digest: await signupControlDigest(document) };\n}\n","import type {\n AdmissionDecision,\n AdmissionGrantDocument,\n AdmissionGrantEnvelope,\n AdmissionGrantInput,\n} from \"./admission-grants-contract\";\nimport { ADMISSION_GRANTS_SCHEMA_VERSION } from \"./admission-grants-contract\";\nimport type { ChapterDb, DbOp } from \"./types\";\nimport { signupControlDigest } from \"./signup-control-canonical\";\nimport { normalizeChapterEmail } from \"./email-identity\";\n\nconst ID = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/;\nconst MAX_GRANTS = 2_000;\nconst MAX_NOTE = 2_000;\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nconst isAdmissionEmail = (value: string): boolean => EMAIL_RE.test(value);\n\n/** Exact email natural key: trim and lowercase, with no provider alias rules. */\nexport function normalizeAdmissionEmail(email: string): string {\n return normalizeChapterEmail(email);\n}\n\n/** Validated normalized admission document or all contract errors. */\nexport type AdmissionGrantValidation =\n | { ok: true; value: AdmissionGrantDocument }\n | { ok: false; errors: readonly string[] };\n\n/** Validate and normalize a complete Parent admission document. */\nexport function validateAdmissionGrantDocument(input: unknown): AdmissionGrantValidation {\n const errors: string[] = [];\n const root = input && typeof input === \"object\" ? input as Record<string, unknown> : {};\n if (root.schemaVersion !== ADMISSION_GRANTS_SCHEMA_VERSION) errors.push(\"document.schemaVersion must be 1\");\n const revision = Number(root.revision);\n const generatedAt = Number(root.generatedAt);\n if (!Number.isSafeInteger(revision) || revision < 1) errors.push(\"document.revision must be a positive integer\");\n if (!Number.isFinite(generatedAt) || generatedAt <= 0) errors.push(\"document.generatedAt must be epoch milliseconds\");\n const source = root.source && typeof root.source === \"object\" ? root.source as Record<string, unknown> : {};\n const target = root.target && typeof root.target === \"object\" ? root.target as Record<string, unknown> : {};\n const sourceId = typeof source.appId === \"string\" ? source.appId : \"\";\n const sourceActor = typeof source.actor === \"string\" ? source.actor.trim() : \"\";\n const chapterId = typeof target.chapterId === \"string\" ? target.chapterId : \"\";\n const environment = typeof target.environment === \"string\" ? target.environment : \"\";\n if (!ID.test(sourceId)) errors.push(\"document.source.appId must be an identifier\");\n if (!sourceActor || sourceActor.length > 256) errors.push(\"document.source.actor must be 1-256 characters\");\n if (!ID.test(chapterId)) errors.push(\"document.target.chapterId must be an identifier\");\n if (!ID.test(environment)) errors.push(\"document.target.environment must be an identifier\");\n if (!Array.isArray(root.grants)) errors.push(\"document.grants must be an array\");\n const rawGrants = Array.isArray(root.grants) ? root.grants : [];\n if (rawGrants.length > MAX_GRANTS) errors.push(`document.grants supports at most ${MAX_GRANTS} entries`);\n const grants: AdmissionGrantInput[] = [];\n const seenIds = new Set<string>();\n const seenEmails = new Set<string>();\n for (const [index, raw] of rawGrants.slice(0, MAX_GRANTS).entries()) {\n const grant = raw && typeof raw === \"object\" ? raw as Record<string, unknown> : {};\n const id = typeof grant.id === \"string\" ? grant.id : \"\";\n const email = typeof grant.email === \"string\" ? grant.email.trim() : \"\";\n const normalized = normalizeAdmissionEmail(email);\n const decision = grant.decision;\n const note = typeof grant.note === \"string\" ? grant.note.trim() : undefined;\n const expiresAt = grant.expiresAt === undefined ? undefined : Number(grant.expiresAt);\n if (!ID.test(id)) errors.push(`document.grants[${index}].id must be an identifier`);\n if (seenIds.has(id)) errors.push(`document.grants repeats id \"${id}\"`);\n if (!isAdmissionEmail(normalized)) errors.push(`document.grants[${index}].email must be valid`);\n if (seenEmails.has(normalized)) errors.push(`document.grants repeats email \"${normalized}\"`);\n if (decision !== \"waive_interview\" && decision !== \"require_interview\") {\n errors.push(`document.grants[${index}].decision is invalid`);\n }\n if (note && note.length > MAX_NOTE) errors.push(`document.grants[${index}].note is too long`);\n if (expiresAt !== undefined && (!Number.isFinite(expiresAt) || expiresAt <= 0)) {\n errors.push(`document.grants[${index}].expiresAt must be epoch milliseconds`);\n }\n seenIds.add(id);\n seenEmails.add(normalized);\n grants.push({\n id,\n email,\n decision: decision as AdmissionDecision,\n ...(note ? { note } : {}),\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n });\n }\n if (errors.length) return { ok: false, errors };\n return {\n ok: true,\n value: {\n schemaVersion: ADMISSION_GRANTS_SCHEMA_VERSION,\n revision,\n generatedAt,\n source: { appId: sourceId, actor: sourceActor },\n target: { chapterId, environment },\n grants,\n },\n };\n}\n\n/** Pair a validated desired-state document with its canonical digest. */\nexport async function createAdmissionGrantEnvelope(document: AdmissionGrantDocument): Promise<AdmissionGrantEnvelope> {\n const checked = validateAdmissionGrantDocument(document);\n if (!checked.ok) throw new TypeError(`Invalid admission grant document: ${checked.errors.join(\"; \")}`);\n return { document: checked.value, digest: await signupControlDigest(checked.value) };\n}\n\n/** Materialized local or Parent admission decision stored by a Chapter. */\nexport interface AdmissionGrantRow {\n id: string;\n sourceGrantId: string;\n sourceScope: \"local\" | \"parent\";\n sourceId: string;\n targetId: string;\n email: string;\n emailNormalized: string;\n decision: AdmissionDecision;\n active: boolean;\n createdAt: number;\n note?: string;\n expiresAt?: number;\n revokedAt?: number;\n consumedAt?: number;\n consumedApplicationId?: string;\n}\n\nconst rows = (value: unknown): Array<Record<string, unknown>> => Array.isArray(value) ? value : [];\n\nfunction asGrant(row: Record<string, unknown>): AdmissionGrantRow | null {\n if (typeof row.id !== \"string\" || typeof row.emailNormalized !== \"string\") return null;\n if (row.sourceScope !== \"local\" && row.sourceScope !== \"parent\") return null;\n if (row.decision !== \"waive_interview\" && row.decision !== \"require_interview\") return null;\n return row as unknown as AdmissionGrantRow;\n}\n\n/** Resolve the effective current decision. Local rows always outrank Parent rows. */\nexport async function findAdmissionGrant(\n db: ChapterDb,\n targetId: string,\n email: string,\n now: number,\n): Promise<AdmissionGrantRow | null> {\n const emailNormalized = normalizeAdmissionEmail(email);\n if (!isAdmissionEmail(emailNormalized)) return null;\n const result = await db.query({ admissionGrants: { $: { where: { emailNormalized }, limit: 100 } } });\n const active = rows(result.admissionGrants)\n .map(asGrant)\n .filter((grant): grant is AdmissionGrantRow => Boolean(\n grant && grant.targetId === targetId && grant.active === true && !grant.revokedAt &&\n (!grant.expiresAt || grant.expiresAt > now) && !grant.consumedApplicationId,\n ))\n .sort((a, b) => {\n const scope = Number(b.sourceScope === \"local\") - Number(a.sourceScope === \"local\");\n return scope || b.createdAt - a.createdAt;\n });\n return active[0] ?? null;\n}\n\n/** Stored receipt for one signed Parent admission revision. */\nexport interface AdmissionGrantRevisionRow {\n id: string;\n sourceId: string;\n targetId: string;\n environment: string;\n revision: number;\n digest: string;\n active: boolean;\n receivedAt: number;\n}\n\nasync function hasAdmissionRevision(\n db: ChapterDb,\n sourceId: string,\n targetId: string,\n environment: string,\n): Promise<boolean> {\n const where = { sourceId, targetId, environment };\n if (db.aggregate) {\n return Number((await db.aggregate(\"admissionGrantRevisions\", { count: true }, { where })).count ?? 0) > 0;\n }\n const found = await db.query({ admissionGrantRevisions: {} });\n return rows(found.admissionGrantRevisions).some((row) =>\n row.sourceId === sourceId && row.targetId === targetId && row.environment === environment);\n}\n\n/** Read the newest received revision without issuing an ordered query over empty history. */\nexport async function loadLatestAdmissionRevision(\n db: ChapterDb,\n sourceId: string,\n targetId: string,\n environment: string,\n): Promise<AdmissionGrantRevisionRow | null> {\n if (!await hasAdmissionRevision(db, sourceId, targetId, environment)) return null;\n const result = await db.query({ admissionGrantRevisions: { $: {\n where: { sourceId, targetId, environment }, order: { revision: \"desc\" }, limit: 1,\n } } });\n const row = rows(result.admissionGrantRevisions)\n .sort((a, b) => Number(b.revision ?? 0) - Number(a.revision ?? 0))[0];\n return row ? row as unknown as AdmissionGrantRevisionRow : null;\n}\n\n/** Replace only Parent-authored rows; local Chapter decisions remain untouched. */\nexport async function materializeAdmissionGrants(\n db: ChapterDb,\n envelope: AdmissionGrantEnvelope,\n previous: AdmissionGrantRevisionRow | null,\n receivedAt: number,\n): Promise<void> {\n const { document, digest } = envelope;\n const current = rows((await db.query({ admissionGrants: { $: {\n where: { sourceScope: \"parent\", sourceId: document.source.appId, targetId: document.target.chapterId },\n limit: MAX_GRANTS,\n } } })).admissionGrants);\n const incomingIds = new Set(document.grants.map((grant) => `admission:parent:${document.source.appId}:${grant.id}`));\n const ops: DbOp[] = [];\n for (const row of current) {\n const id = String(row.id ?? \"\");\n if (id && !incomingIds.has(id)) ops.push({ t: \"update\", ns: \"admissionGrants\", id, attrs: {\n active: false, revokedAt: receivedAt, revokedBy: document.source.actor,\n updatedAt: receivedAt, updatedBy: document.source.actor,\n } });\n }\n for (const grant of document.grants) {\n const id = `admission:parent:${document.source.appId}:${grant.id}`;\n const existing = current.find((row) => row.id === id);\n ops.push({ t: \"update\", ns: \"admissionGrants\", id, attrs: {\n id,\n sourceGrantId: grant.id,\n sourceScope: \"parent\",\n sourceId: document.source.appId,\n targetId: document.target.chapterId,\n email: grant.email,\n emailNormalized: normalizeAdmissionEmail(grant.email),\n decision: grant.decision,\n ...(grant.note ? { note: grant.note } : {}),\n ...(grant.expiresAt ? { expiresAt: grant.expiresAt } : {}),\n active: true,\n sourceRevision: document.revision,\n createdAt: Number(existing?.createdAt ?? receivedAt),\n createdBy: String(existing?.createdBy ?? document.source.actor),\n updatedAt: receivedAt,\n updatedBy: document.source.actor,\n } });\n const retract = [\n ...(!grant.note && existing?.note !== undefined ? [\"note\"] : []),\n ...(grant.expiresAt === undefined && existing?.expiresAt !== undefined ? [\"expiresAt\"] : []),\n ];\n if (retract.length) ops.push({ t: \"retract\", ns: \"admissionGrants\", id, attrs: retract });\n }\n if (previous?.active) ops.push({ t: \"update\", ns: \"admissionGrantRevisions\", id: previous.id, attrs: { active: false } });\n const revisionId = `admission-revision:${document.source.appId}:${document.target.environment}:${document.revision}`;\n ops.push({ t: \"update\", ns: \"admissionGrantRevisions\", id: revisionId, attrs: {\n id: revisionId,\n sourceId: document.source.appId,\n targetId: document.target.chapterId,\n environment: document.target.environment,\n revision: document.revision,\n digest,\n active: true,\n receivedAt,\n } });\n await db.transact(ops, { mutationId: `admission-grants:${document.source.appId}:${document.target.environment}:${document.revision}:${digest}` });\n}\n","import { canBook } from \"./pipeline\";\nimport type { ResolvedPipeline } from \"./types\";\n\n/** Canonical next action or browser-visible step after application submission. */\nexport type JoinContinuation = \"payment\" | \"paymentPending\" | \"booking\" | \"approve\" | \"accepted\";\n\n/** One server-side decision for submit, resume, and payment completion. */\nexport function resolveJoinContinuation(input: {\n status: string;\n initialStatus: string;\n pipeline: ResolvedPipeline;\n payable: boolean;\n subscriptionStarted: boolean;\n interviewWaived: boolean;\n}): JoinContinuation | null {\n if (input.status === \"approved\") return \"accepted\";\n if (input.interviewWaived) {\n if (!input.payable) return \"approve\";\n if (input.status === input.initialStatus) {\n return input.subscriptionStarted ? \"paymentPending\" : \"payment\";\n }\n return \"approve\";\n }\n if (!input.payable) return \"booking\";\n if (input.status === input.initialStatus) {\n return input.subscriptionStarted ? \"paymentPending\" : \"payment\";\n }\n if (canBook(input.status, input.pipeline)) return \"booking\";\n return null;\n}\n","/** Current nested gift-catalog version inside signup-control. */\nexport const GIFT_OFFER_CATALOG_VERSION = 1 as const;\n/** Maximum signed gift SKUs accepted in one catalog revision. */\nexport const MAX_GIFT_OFFERS = 20;\n\n/** Membership tier or standalone entitlement fulfilled by redemption. */\nexport type GiftOfferTarget =\n | { type: \"tier\"; tierId: string }\n | { type: \"entitlement\"; entitlementKey: string };\n\n/** Server-authored gift SKU; provider identifiers never reach public config. */\nexport interface GiftOffer {\n id: string;\n target: GiftOfferTarget;\n billingMode: \"one_time\" | \"subscription\";\n stripePriceId: string;\n priceCents: number;\n currency: string;\n redemptionLifetimeHours: number;\n activeFrom?: number;\n activeUntil?: number;\n title: string;\n description: string;\n ctaLabel: string;\n}\n\n/** Versioned bounded collection delegated through signed signup control. */\nexport interface GiftOfferCatalog {\n schemaVersion: typeof GIFT_OFFER_CATALOG_VERSION;\n offers: readonly GiftOffer[];\n}\n\n/** Provider-free gift offer shape rendered by Chapter and exact CMS previews. */\nexport type PublicGiftOffer = Omit<GiftOffer, \"stripePriceId\" | \"target\">;\n\n/** Result of validating and normalizing an untrusted gift catalog. */\nexport type GiftOfferValidation =\n | { ok: true; value: GiftOfferCatalog }\n | { ok: false; errors: readonly string[] };\n\nconst ID = /^[a-z][a-z0-9-]{1,79}$/;\nconst PRICE = /^price_[A-Za-z0-9]{12,}$/;\nconst CURRENCY = /^[a-z]{3}$/;\nconst record = (value: unknown): Record<string, unknown> | null =>\n value && typeof value === \"object\" && !Array.isArray(value) ? value as Record<string, unknown> : null;\nconst text = (value: unknown, path: string, errors: string[], max: number): string => {\n if (typeof value !== \"string\" || !value.trim()) { errors.push(`${path} is required`); return \"\"; }\n if (value.trim().length > max) errors.push(`${path} must be at most ${max} characters`);\n return value.trim();\n};\n\n/** Validate and normalize gift offers against the same document's tier ids. */\nexport function validateGiftOfferCatalog(input: unknown, tierIds: ReadonlySet<string>): GiftOfferValidation {\n const errors: string[] = [];\n const root = record(input);\n if (!root) return { ok: false, errors: [\"document.giftOffers must be an object\"] };\n for (const key of Object.keys(root)) if (key !== \"schemaVersion\" && key !== \"offers\") errors.push(`document.giftOffers.${key} is not supported`);\n if (root.schemaVersion !== GIFT_OFFER_CATALOG_VERSION) errors.push(\"document.giftOffers.schemaVersion must be 1\");\n if (!Array.isArray(root.offers)) errors.push(\"document.giftOffers.offers must be an array\");\n const rawOffers = Array.isArray(root.offers) ? root.offers : [];\n if (rawOffers.length > MAX_GIFT_OFFERS) errors.push(`document.giftOffers.offers supports at most ${MAX_GIFT_OFFERS} entries`);\n const ids = new Set<string>();\n const offers: GiftOffer[] = [];\n for (const [index, raw] of rawOffers.slice(0, MAX_GIFT_OFFERS).entries()) {\n const path = `document.giftOffers.offers[${index}]`;\n const item = record(raw);\n if (!item) { errors.push(`${path} must be an object`); continue; }\n const allowed = new Set([\"id\", \"target\", \"billingMode\", \"stripePriceId\", \"priceCents\", \"currency\", \"redemptionLifetimeHours\", \"activeFrom\", \"activeUntil\", \"title\", \"description\", \"ctaLabel\"]);\n for (const key of Object.keys(item)) if (!allowed.has(key)) errors.push(`${path}.${key} is not supported`);\n const id = text(item.id, `${path}.id`, errors, 80);\n if (id && !ID.test(id)) errors.push(`${path}.id must be a lowercase kebab-case id`);\n if (ids.has(id)) errors.push(`${path}.id duplicates \"${id}\"`);\n ids.add(id);\n const targetRaw = record(item.target);\n let target: GiftOfferTarget = { type: \"entitlement\", entitlementKey: \"invalid\" };\n if (targetRaw?.type === \"tier\") {\n const tierId = text(targetRaw.tierId, `${path}.target.tierId`, errors, 80);\n if (!tierIds.has(tierId)) errors.push(`${path}.target.tierId must reference a declared tier`);\n target = { type: \"tier\", tierId };\n } else if (targetRaw?.type === \"entitlement\") {\n const entitlementKey = text(targetRaw.entitlementKey, `${path}.target.entitlementKey`, errors, 80);\n if (entitlementKey && !ID.test(entitlementKey)) errors.push(`${path}.target.entitlementKey must be a lowercase kebab-case id`);\n target = { type: \"entitlement\", entitlementKey };\n } else errors.push(`${path}.target.type must be tier or entitlement`);\n if (item.billingMode !== \"one_time\" && item.billingMode !== \"subscription\") errors.push(`${path}.billingMode must be one_time or subscription`);\n const stripePriceId = text(item.stripePriceId, `${path}.stripePriceId`, errors, 128);\n if (stripePriceId && !PRICE.test(stripePriceId)) errors.push(`${path}.stripePriceId must be a real Stripe Price id`);\n if (!Number.isSafeInteger(item.priceCents) || Number(item.priceCents) < 1 || Number(item.priceCents) > 100_000_000) errors.push(`${path}.priceCents must be an integer from 1 to 100,000,000`);\n const currency = typeof item.currency === \"string\" ? item.currency.trim().toLowerCase() : \"\";\n if (!CURRENCY.test(currency)) errors.push(`${path}.currency must be a lowercase ISO currency code`);\n const lifetime = Number(item.redemptionLifetimeHours);\n if (!Number.isSafeInteger(lifetime) || lifetime < 1 || lifetime > 8_760) errors.push(`${path}.redemptionLifetimeHours must be an integer from 1 to 8760`);\n const activeFrom = item.activeFrom === undefined ? undefined : Number(item.activeFrom);\n const activeUntil = item.activeUntil === undefined ? undefined : Number(item.activeUntil);\n if (activeFrom !== undefined && (!Number.isSafeInteger(activeFrom) || activeFrom < 1)) errors.push(`${path}.activeFrom must be epoch milliseconds`);\n if (activeUntil !== undefined && (!Number.isSafeInteger(activeUntil) || activeUntil < 1)) errors.push(`${path}.activeUntil must be epoch milliseconds`);\n if (activeFrom !== undefined && activeUntil !== undefined && activeUntil <= activeFrom) errors.push(`${path}.activeUntil must follow activeFrom`);\n offers.push({\n id, target, billingMode: item.billingMode as GiftOffer[\"billingMode\"], stripePriceId,\n priceCents: Number(item.priceCents), currency, redemptionLifetimeHours: lifetime,\n ...(activeFrom !== undefined ? { activeFrom } : {}), ...(activeUntil !== undefined ? { activeUntil } : {}),\n title: text(item.title, `${path}.title`, errors, 160), description: text(item.description, `${path}.description`, errors, 2_000),\n ctaLabel: text(item.ctaLabel, `${path}.ctaLabel`, errors, 120),\n });\n }\n return errors.length ? { ok: false, errors } : { ok: true, value: { schemaVersion: 1, offers } };\n}\n\n/** Whether an offer is active at an exact server time. */\nexport const giftOfferActive = (offer: GiftOffer, now: number): boolean =>\n (!offer.activeFrom || offer.activeFrom <= now) && (!offer.activeUntil || offer.activeUntil > now);\n\n/** Public provider-free active catalog projection. */\nexport function publicGiftOffers(catalog: GiftOfferCatalog | undefined, now: number): PublicGiftOffer[] {\n return (catalog?.offers ?? []).filter((offer) => giftOfferActive(offer, now)).map(({ stripePriceId: _stripe, target: _target, ...offer }) => offer);\n}\n\n/** Resolve one currently active server-authoritative offer. */\nexport function findGiftOffer(catalog: GiftOfferCatalog | undefined, offerId: string, now: number): GiftOffer | null {\n return catalog?.offers.find((offer) => offer.id === offerId && giftOfferActive(offer, now)) ?? null;\n}\n","// Leader → follower projection of a deliberately allowlisted CRM field set.\n//\n// Invariants (package-enforced so no site re-derives them):\n// - One-way: the chapter never writes back to the hub through this path.\n// - Idempotent: every received record carries the leader's stable site +\n// record identity. A structured crm_record_origin row maps that identity to\n// the local CRM record, so a re-share updates instead of duplicating even\n// after an email/domain changes. Legacy tags remain as a migration bridge.\n// - Natural-key convergence: a person unifies by primary email and a business\n// by its configured domain slot (then name), so an arriving applicant and a\n// prior leader share compose into one person.\n// - Operational state stays local. Pipeline/account/billing state is not copied\n// into another site's authority; the push transfers the shared record fields.\n//\n// Reuses @odla-ai/crm's record ops (full validation via crm.prepare), driven by\n// the resolved chapter CRM engine + the structural ChapterDb.\nimport {\n createRecord,\n getRecordByOrigin,\n updateRecord,\n upsertRecordOrigin,\n} from \"@odla-ai/crm\";\nimport type { Crm, CrmRecord } from \"@odla-ai/crm\";\nimport type { ChapterDb, ResolvedNetworkTarget } from \"./types\";\nimport {\n DEFAULT_SHARE_FIELDS,\n type NormalizedSharedRecord,\n type ProjectionDeps,\n type SharedBusiness,\n type SharedPerson,\n type SharedRecord,\n} from \"./network-contract\";\nexport { DEFAULT_SHARE_FIELDS } from \"./network-contract\";\nexport type {\n NetworkRollup, NetworkRollupTarget,\n NetworkSnapshot,\n ProjectionDeps,\n SharedBusiness,\n SharedPerson,\n SharedRecord,\n SharedRecordV1,\n SharedRecordV2,\n} from \"./network-contract\";\n\n/** Map a shared prospect to a crm `person` input (only the fields the default\n * person type accepts). Name falls back to first+last, then the email. */\nexport function sharedPersonInput(person: SharedPerson): Record<string, unknown> {\n const email = person.email.toLowerCase();\n const fullName = [person.firstName, person.lastName].filter(Boolean).join(\" \").trim();\n const input: Record<string, unknown> = { name: person.name ?? fullName ?? email, email };\n if (input.name === \"\") input.name = email;\n if (person.firstName) input.firstName = person.firstName;\n if (person.lastName) input.lastName = person.lastName;\n if (person.phone) input.phone = person.phone;\n if (person.linkedin) input.linkedin = person.linkedin;\n return input;\n}\n\nfunction shortHash(value: string): string {\n let a = 0x811c9dc5;\n let b = 0x9e3779b9;\n for (let i = 0; i < value.length; i += 1) {\n const n = value.charCodeAt(i);\n a = Math.imul(a ^ n, 0x01000193);\n b = Math.imul(b ^ n, 0x85ebca6b);\n }\n return `${(a >>> 0).toString(36)}${(b >>> 0).toString(36)}`;\n}\n\n/** Backward-compatible display tag retained while structured origin rows are\n * the durable leader-id → local-record mapping. */\nexport function networkSourceTag(type: string, hubRecordId: string, sourceId?: string): string {\n const typeKey = type.toLowerCase();\n const readable = /^[a-z0-9_-]+$/.test(hubRecordId);\n const prefix = sourceId ? `network:${sourceId.toLowerCase()}:${typeKey}` : `network:${typeKey}`;\n const raw = `${prefix}:${hubRecordId}`;\n if (readable && raw.length <= 64) return raw;\n return `network:${typeKey.slice(0, 16)}:${shortHash(`${sourceId ?? \"\"}\\u0000${type}\\u0000${hubRecordId}`)}`;\n}\n\n/** Normalize the backwards-compatible person/business shapes into the versioned\n * generic record envelope the receiver writes. */\nexport function normalizeSharedRecord(\n record: SharedPerson | SharedBusiness | SharedRecord,\n fallbackSourceId = \"legacy-source\",\n): NormalizedSharedRecord {\n if (\"input\" in record && record.version === 2) {\n return {\n version: 2,\n sourceId: record.source.siteId,\n sourceRecordId: record.source.recordId,\n type: record.type,\n input: record.input,\n };\n }\n if (\"input\" in record) {\n return {\n version: 1,\n sourceId: fallbackSourceId,\n sourceRecordId: record.hubRecordId,\n type: record.type,\n input: record.input,\n };\n }\n if (\"type\" in record && record.type === \"company\") {\n const input: Record<string, unknown> = { name: record.name };\n for (const key of [\"domain\", \"industry\", \"location\", \"linkedin\", \"notes\"] as const) {\n if (record[key]) input[key] = record[key];\n }\n return {\n version: 1,\n sourceId: fallbackSourceId,\n sourceRecordId: record.hubRecordId,\n type: \"company\",\n input,\n };\n }\n return {\n version: 1,\n sourceId: fallbackSourceId,\n sourceRecordId: record.hubRecordId,\n type: \"person\",\n input: sharedPersonInput(record),\n };\n}\n\n/** Build the allowlisted payload sent from one leader CRM record to a target.\n * A target with an explicit `fields` map only accepts the types it lists. */\nexport function sharedRecordFromCrm(\n crm: Crm,\n record: CrmRecord,\n target: ResolvedNetworkTarget,\n sourceId?: string,\n): SharedRecord {\n if (target.fields && !target.fields[record.type]) {\n throw new Error(`${target.name} does not accept \"${record.type}\" records`);\n }\n const def = crm.type(record.type);\n const fields = target.fields?.[record.type] ?? DEFAULT_SHARE_FIELDS[record.type];\n if (!fields) {\n throw new Error(`${target.name} requires an explicit field allowlist for \"${record.type}\" records`);\n }\n const nameField = def.nameField ?? \"name\";\n const input: Record<string, unknown> = {};\n for (const field of new Set([nameField, ...fields])) {\n const value = record.fields?.[field];\n if (value !== undefined) input[field] = value;\n }\n if (input[nameField] === undefined) input[nameField] = record.name;\n return sourceId\n ? { version: 2, source: { siteId: sourceId, recordId: record.id }, type: record.type, input }\n : { version: 1, type: record.type, hubRecordId: record.id, input };\n}\n\n// Resolve an existing crm_record person by lowercased primaryEmail and update it,\n// else create one under the given mutationId. The shared core of every one-way\n// person projection (hub share, arriving applicant).\nasync function upsertPerson(\n deps: ProjectionDeps,\n opts: { email: string; input: Record<string, unknown>; mutationId: string },\n): Promise<{ recordId: string }> {\n const email = opts.email.toLowerCase();\n const crmDeps = { crm: deps.crm, db: deps.db as never, now: deps.now, newId: deps.newId };\n const { crm_record } = await deps.db.query({ crm_record: { $: { where: { type: \"person\", primaryEmail: email }, limit: 1 } } });\n const existing = crm_record?.[0];\n if (existing && typeof existing.id === \"string\") {\n await updateRecord(crmDeps, { id: existing.id, input: opts.input });\n return { recordId: existing.id };\n }\n const created = await createRecord(crmDeps, { type: \"person\", input: opts.input, mutationId: opts.mutationId });\n return { recordId: created.id };\n}\n\nasync function findSharedRecord(\n deps: ProjectionDeps,\n record: NormalizedSharedRecord,\n tag: string,\n): Promise<Record<string, unknown> | undefined> {\n const structured = await getRecordByOrigin(\n { crm: deps.crm, db: deps.db as never, now: deps.now, newId: deps.newId },\n record.sourceId,\n record.sourceRecordId,\n );\n if (structured) return structured as unknown as Record<string, unknown>;\n const mapped = await deps.db.query({ crm_tag: { $: { where: { tag }, limit: 1 } } });\n const mappedId = mapped.crm_tag?.[0]?.recordId;\n if (typeof mappedId === \"string\") {\n const found = await deps.db.query({ crm_record: { $: { where: { id: mappedId }, limit: 1 } } });\n if (found.crm_record?.[0]) return found.crm_record[0];\n }\n const def = deps.crm.type(record.type);\n const emailField = def.emailField;\n if (emailField && typeof record.input[emailField] === \"string\") {\n const primaryEmail = record.input[emailField].toLowerCase();\n const found = await deps.db.query({\n crm_record: { $: { where: { type: record.type, primaryEmail }, limit: 1 } },\n });\n if (found.crm_record?.[0]) return found.crm_record[0];\n }\n const domain = record.input.domain;\n const domainSlot = def.fields.domain?.slot;\n if (typeof domain === \"string\" && domainSlot) {\n const found = await deps.db.query({\n crm_record: { $: { where: { type: record.type, [domainSlot]: domain }, limit: 1 } },\n });\n if (found.crm_record?.[0]) return found.crm_record[0];\n }\n const nameField = def.nameField ?? \"name\";\n const name = record.input[nameField];\n if (record.type === \"company\" && typeof name === \"string\" && name.trim()) {\n const found = await deps.db.query({\n crm_record: { $: { where: { type: record.type, name: name.trim() }, limit: 1 } },\n });\n if (found.crm_record?.[0]) return found.crm_record[0];\n }\n return undefined;\n}\n\n/**\n * Upsert a leader-shared CRM record into this follower. Accepts the original\n * person wire shape plus the versioned generic shape. Re-shares resolve through\n * a durable provenance tag; people/businesses also converge by natural key.\n */\nexport async function projectSharedRecord(\n deps: ProjectionDeps,\n shared: SharedPerson | SharedBusiness | SharedRecord,\n options: { sourceId?: string; sourceUrl?: string } = {},\n): Promise<{ recordId: string }> {\n const record = normalizeSharedRecord(shared, options.sourceId);\n if (!record.type.trim() || !record.sourceId.trim() || !record.sourceRecordId.trim()) {\n throw new Error(\"type, source site id, and source record id must be non-empty\");\n }\n if (options.sourceId && options.sourceId !== record.sourceId) {\n throw new Error(\"signed sender does not match payload source\");\n }\n const tag = networkSourceTag(record.type, record.sourceRecordId, record.version === 2 ? record.sourceId : undefined);\n const crmDeps = { crm: deps.crm, db: deps.db as never, now: deps.now, newId: deps.newId };\n const existing = await findSharedRecord(deps, record, tag);\n let recordId: string;\n if (existing && typeof existing.id === \"string\") {\n // Do not use one permanent mutation id for updates: a later leader edit is a\n // new desired state and must not be mistaken for a retry of an older push.\n await updateRecord(crmDeps, { id: existing.id, input: record.input });\n recordId = existing.id;\n } else {\n // A deterministic id makes concurrent first deliveries converge even when\n // both requests observe no provenance row before either transaction lands.\n recordId = `network_${shortHash(`${record.sourceId}\\u0000${record.type}\\u0000${record.sourceRecordId}`)}`;\n await createRecord({ ...crmDeps, newId: () => recordId }, {\n type: record.type,\n input: record.input,\n mutationId: `share-create:${tag}`,\n });\n }\n await deps.db.transact(\n [{ t: \"update\", ns: \"crm_tag\", id: tag, attrs: { key: `${recordId}:${tag}`, recordId, tag, createdAt: deps.now() } }],\n { mutationId: `share-map:${tag}:${recordId}` },\n );\n await upsertRecordOrigin(crmDeps, {\n recordId,\n sourceId: record.sourceId,\n sourceRecordId: record.sourceRecordId,\n ...(options.sourceUrl ? { sourceUrl: options.sourceUrl } : {}),\n payloadVersion: record.version,\n });\n return { recordId };\n}\n\n/** An arriving applicant, as far as the CRM projection cares. `extra` carries the\n * site-configured `crmFields` (values from the application), merged on top of the\n * built-in identity/contact set. */\nexport interface Applicant {\n applicationId: string;\n email: string;\n firstName?: string;\n lastName?: string;\n phone?: string;\n linkedin?: string;\n extra?: Record<string, unknown>;\n}\n\n/**\n * Project an arriving applicant into this chapter's `crm_record`, so a new\n * application shows up in the CRM immediately, unified by email with any prior\n * record. Idempotent per application (`apply:${applicationId}`). Best-effort at\n * the call site — a projection failure never fails the application.\n *\n * `extra` fields (a site's `crmFields`) are merged on top of the base person. If\n * an extra field is not on the crm person type, crm validation throws — so the\n * projection retries with the base person alone, ensuring a misconfigured\n * enrichment never silently drops the applicant from the CRM entirely.\n */\nexport async function projectApplicant(deps: ProjectionDeps, applicant: Applicant): Promise<{ recordId: string }> {\n const base = sharedPersonInput({\n email: applicant.email,\n firstName: applicant.firstName,\n lastName: applicant.lastName,\n phone: applicant.phone,\n linkedin: applicant.linkedin,\n hubRecordId: applicant.applicationId,\n });\n const mutationId = `apply:${applicant.applicationId}`;\n const extra = applicant.extra ?? {};\n if (Object.keys(extra).length === 0) return upsertPerson(deps, { email: applicant.email, input: base, mutationId });\n try {\n return await upsertPerson(deps, { email: applicant.email, input: { ...base, ...extra }, mutationId });\n } catch {\n return upsertPerson(deps, { email: applicant.email, input: base, mutationId });\n }\n}\n","import type { Crm, TypeSummary } from \"@odla-ai/crm\";\nimport type { ChapterDb } from \"./types\";\n\n/** The contact data the hub shares for a prospect. `hubRecordId` is the stable\n * idempotency key (the hub's crm_record id). */\nexport interface SharedPerson {\n email: string;\n name?: string;\n firstName?: string;\n lastName?: string;\n phone?: string;\n linkedin?: string;\n hubRecordId: string;\n}\n\n/** Convenience wire shape for sharing the default `company` CRM type. */\nexport interface SharedBusiness {\n type: \"company\";\n name: string;\n domain?: string;\n industry?: string;\n location?: string;\n linkedin?: string;\n notes?: string;\n hubRecordId: string;\n}\n\n/** Versioned generic wire shape. `input` is validated against the follower's\n * own CRM type before any write, so a leader cannot smuggle undeclared fields. */\nexport interface SharedRecordV1 {\n version: 1;\n type: string;\n hubRecordId: string;\n input: Record<string, unknown>;\n}\n\n/** Current wire envelope. `source.siteId` prevents records from two leaders\n * with the same local id from colliding in a follower CRM. */\nexport interface SharedRecordV2 {\n version: 2;\n source: { siteId: string; recordId: string };\n type: string;\n input: Record<string, unknown>;\n}\n\n/** Accepted generic share envelopes. Version 1 remains readable for migration. */\nexport type SharedRecord = SharedRecordV1 | SharedRecordV2;\n\n/** Privacy-bounded follower status returned to an authenticated leader. */\nexport interface NetworkSnapshot {\n version: 1;\n site: { id: string; name: string; mode: string };\n generatedAt: number;\n types: TypeSummary[];\n}\n\n/** One configured target's latest live result in a leader rollup. */\nexport interface NetworkRollupTarget {\n id: string;\n name: string;\n url: string;\n available: boolean;\n generatedAt?: number;\n types?: TypeSummary[];\n error?: string;\n}\n\n/** Cross-target totals returned to the local leader admin. */\nexport interface NetworkRollup {\n configured: number;\n available: number;\n totalRecords: number;\n types: Array<{ type: string; total: number; stages: Record<string, number> }>;\n targets: NetworkRollupTarget[];\n}\n\n/** Privacy-bounded CRM record returned by a follower to one configured,\n * authenticated reader. */\nexport interface NetworkRecord {\n id: string;\n type: string;\n name: string;\n stage?: string;\n fields: Record<string, unknown>;\n createdAt: number;\n updatedAt: number;\n}\n\n/** One bounded, offset-paged follower record window. */\nexport interface NetworkRecordPage {\n version: 1;\n site: { id: string; name: string };\n type: string;\n records: NetworkRecord[];\n total: number;\n limit: number;\n offset: number;\n}\n\n/** Leader-private note attached to a stable remote record identity. */\nexport interface NetworkRecordNote {\n id: string;\n targetId: string;\n recordType: string;\n recordId: string;\n body: string;\n authorId: string;\n authorEmail?: string;\n createdAt: number;\n}\n\n/** A note deliberately shared across the federation edge and stored in the\n * follower CRM activity feed. Unlike NetworkRecordNote, this is visible to\n * the follower's own CRM admins. */\nexport interface NetworkSharedNote {\n id: string;\n sourceId: string;\n recordType: string;\n recordId: string;\n body: string;\n createdAt: number;\n}\n\nexport interface NormalizedSharedRecord {\n version: 1 | 2;\n sourceId: string;\n sourceRecordId: string;\n type: string;\n input: Record<string, unknown>;\n}\n\n/** Dependencies for applying a shared projection. */\nexport interface ProjectionDeps {\n crm: Crm;\n db: ChapterDb;\n now: () => number;\n newId: () => string;\n}\n\n/** Safe defaults when a target does not declare an explicit field allowlist. */\nexport const DEFAULT_SHARE_FIELDS: Readonly<Record<string, readonly string[]>> = {\n person: [\"name\", \"email\", \"firstName\", \"lastName\", \"phone\", \"linkedin\"],\n company: [\"name\", \"domain\", \"industry\", \"location\", \"linkedin\", \"notes\"],\n};\n","// The OPERATIONAL slice of the one-way person projection: applications + $users\n// -> crm_record, mirroring pipeline stage, a billing snapshot, and the Clerk\n// identity link. `network.ts` projects identity/contact on submit; this adds the\n// operational state the admin surface and the hub read from, so the pipeline\n// stays authoritative in `applications.status` while the CRM carries one\n// relationship surface over the person. Fired AFTER the authoritative write and\n// wrapped in `.catch` at every call site: a CRM hiccup never 5xxs a lifecycle op.\n//\n// Idempotent by construction — every sync resolves the person by lowercased\n// primary email first, so re-running (including the backfill route) updates in\n// place. Generalized from the reference site: the field set is the site's\n// configured `crmFields`, not a hardcoded list.\nimport { createRecord, updateRecord, setStage, linkIdentity } from \"@odla-ai/crm\";\nimport { sharedPersonInput } from \"./network\";\nimport type { ProjectionDeps } from \"./network\";\nimport type { Chapter, ChapterDb } from \"./types\";\n\nconst str = (v: unknown): string => (typeof v === \"string\" ? v : v == null ? \"\" : String(v));\n\n/** Build the projection deps from a worker request's db + context.\n *\n * Shared so every route that writes `applications.status` mirrors it the same\n * way. Status is written from four places (admin approve, admin PATCH, the\n * Stripe webhook, and booking) and the admin dashboard reads its pipeline from\n * `crm_record.stage`, so a route that skips the mirror silently reports the\n * wrong funnel. */\nexport const crmDeps = (\n db: ChapterDb,\n ctx: { chapter: Chapter },\n): ProjectionDeps & { chapter: Chapter } => ({\n crm: ctx.chapter.crm,\n db,\n now: () => Date.now(),\n newId: () => crypto.randomUUID(),\n chapter: ctx.chapter,\n});\n\n/** The crm `person` input for one application row: the built-in identity/contact\n * fields plus each configured `crmFields` value present on the row. */\nexport function personInputFromApp(chapter: Chapter, app: Record<string, unknown>): Record<string, unknown> {\n const input = sharedPersonInput({\n email: str(app.email),\n firstName: str(app.firstName) || undefined,\n lastName: str(app.lastName) || undefined,\n phone: str(app.phone) || undefined,\n linkedin: str(app.linkedin) || undefined,\n hubRecordId: str(app.id),\n });\n for (const f of chapter.application.crmFields) {\n if (app[f] !== undefined) input[f] = app[f];\n }\n if (app.id !== undefined) input.applicationId = str(app.id);\n return input;\n}\n\n// Promoted billing-facet columns derived from the application's Stripe fields +\n// status. Written directly (not through createRecord/updateRecord, which never\n// touch promoted columns), so they never clobber the person input.\nfunction billingColumns(app: Record<string, unknown>): Record<string, unknown> {\n const status = str(app.status);\n const paid = Boolean(app.stripeSubscriptionId) && status !== \"refunded\";\n const billingStatus = status === \"refunded\" ? \"refunded\" : app.canceled === true ? \"canceled\" : paid ? \"active\" : \"none\";\n const cols: Record<string, unknown> = { billingStatus };\n if (app.stripeCustomerId) cols.stripeCustomerId = str(app.stripeCustomerId);\n if (app.stripeSubscriptionId) cols.subscriptionId = str(app.stripeSubscriptionId);\n if (typeof app.renewalAt === \"number\") cols.renewalAt = app.renewalAt;\n return cols;\n}\n\n/** Upsert the person record for one application (or a synthetic `{ email,\n * firstName }` account row) and mirror its stage, billing snapshot, and Clerk\n * identity. `stage` is the `applications.status` to mirror — omit for\n * account-only rows not in the pipeline. Throws on failure (the backfill route\n * counts; the operational call sites wrap in `.catch`). */\nexport async function syncApplicationToCrm(\n deps: ProjectionDeps & { chapter: Chapter },\n opts: { app: Record<string, unknown>; stage?: string },\n): Promise<string | null> {\n const emailKey = str(opts.app.email).toLowerCase();\n if (!emailKey) return null;\n // The narrower shape the crm record helpers take (no chapter).\n const recordDeps = { crm: deps.crm, db: deps.db as never, now: deps.now, newId: deps.newId };\n const input = personInputFromApp(deps.chapter, opts.app);\n\n const { crm_record } = await deps.db.query({\n crm_record: { $: { where: { type: \"person\", primaryEmail: emailKey }, limit: 1 } },\n });\n const existing = crm_record?.[0] ?? null;\n const stage = opts.stage || undefined;\n\n let recordId: string;\n if (existing && typeof existing.id === \"string\") {\n recordId = existing.id;\n await updateRecord(recordDeps, { id: recordId, input });\n } else {\n const created = await createRecord(recordDeps, { type: \"person\", input, ...(stage ? { stage } : {}) });\n recordId = created.id;\n }\n\n // Stage mirror: move only on an actual change, under a stable mutationId so a\n // replay never piles up duplicate stage_change activities. Best-effort — a\n // stage not on the crm person type must not fail the whole sync.\n if (existing && stage && existing.stage !== stage) {\n await setStage(recordDeps, { id: recordId, to: stage, authorId: \"system\", mutationId: `crm:stage:${recordId}:${stage}` }).catch(() => undefined);\n }\n\n await deps.db.transact([{ t: \"update\", ns: \"crm_record\", id: recordId, attrs: billingColumns(opts.app) }]);\n\n // Identity link: stamps clerkUserId when a $users row matches the email; a\n // no-op until the person has an account. Best-effort — a just-created record\n // can briefly lag the read, and the link retries on the next sync.\n await linkIdentity(recordDeps, { recordId, email: emailKey, mutationId: `crm:link:${recordId}:${emailKey}` }).catch(() => undefined);\n\n return recordId;\n}\n\n/** Backfill / repair: project every application (newest per person) and every\n * account-only `$users` row into the CRM. Idempotent (safe to re-run). Dev\n * volumes fit one 1000-row page. Returns `{ synced, errors }`. */\nexport async function backfillCrm(deps: ProjectionDeps & { chapter: Chapter }): Promise<{ synced: number; errors: Array<{ email: string; error: string }> }> {\n const data = await deps.db.query({\n applications: { $: { order: { createdAt: \"desc\" }, limit: 1000 } },\n $users: { $: { limit: 1000 } },\n });\n const seen = new Set<string>();\n let synced = 0;\n const errors: Array<{ email: string; error: string }> = [];\n\n const run = async (app: Record<string, unknown>, stage?: string): Promise<void> => {\n const key = str(app.email).toLowerCase();\n if (!key || seen.has(key)) return; // newest-first: one record per person\n seen.add(key);\n try {\n await syncApplicationToCrm(deps, { app, stage });\n synced += 1;\n } catch (err) {\n errors.push({ email: key, error: err instanceof Error ? err.message : String(err) });\n }\n };\n\n for (const a of (data.applications ?? []) as Array<Record<string, unknown>>) await run(a, str(a.status));\n for (const u of (data.$users ?? []) as Array<Record<string, unknown>>) {\n if (u.deleted === true) continue;\n await run({ email: u.email, firstName: str(u.name) });\n }\n return { synced, errors };\n}\n","// Pure aggregation helpers for the admin dashboard: a weekly time-series bucketer\n// and the annualized-run-rate math for a Stripe subscription. Kept out of the\n// route so both dashboard and billing share one definition and it is unit-tested\n// without a network call.\n\n/** Bucket `{ t, v }` points into the last `weeks` weekly buckets ending at `now`\n * (epoch ms), summing `v` per bucket. Returns oldest→newest `{ weekStart, value\n * }`, so a caller renders a sparkline directly. Points outside the window are\n * ignored. */\nexport function bucketSeries(\n points: Array<{ t: number; v: number }>,\n now: number,\n weeks = 12,\n): Array<{ weekStart: number; value: number }> {\n const WEEK = 7 * 86_400_000;\n const end = now;\n const start = end - weeks * WEEK;\n const buckets = Array.from({ length: weeks }, (_, i) => ({ weekStart: start + i * WEEK, value: 0 }));\n for (const p of points) {\n if (!Number.isFinite(p.t) || p.t < start || p.t > end) continue;\n const idx = Math.min(weeks - 1, Math.floor((p.t - start) / WEEK));\n const bucket = buckets[idx];\n if (bucket) bucket.value += Number.isFinite(p.v) ? p.v : 0;\n }\n return buckets;\n}\n\n/** Labels and current/previous values for one dashboard comparison window. */\nexport interface DashboardMetricSeries {\n labels: string[];\n current: number[];\n previous: number[];\n}\n\n/** Week-over-week and month-over-month series consumed by MetricWidget. */\nexport interface DashboardMetricData {\n wow: DashboardMetricSeries;\n mom: DashboardMetricSeries;\n}\n\nfunction periodSeries(\n points: Array<{ t: number; v: number }>,\n now: number,\n count: number,\n periodMs: number,\n): DashboardMetricSeries {\n const start = now - count * periodMs;\n const previousStart = start - count * periodMs;\n const current = Array.from({ length: count }, () => 0);\n const previous = Array.from({ length: count }, () => 0);\n for (const point of points) {\n if (!Number.isFinite(point.t) || !Number.isFinite(point.v)) continue;\n if (point.t >= start && point.t <= now) {\n const index = Math.min(count - 1, Math.floor((point.t - start) / periodMs));\n current[index] = (current[index] ?? 0) + point.v;\n } else if (point.t >= previousStart && point.t < start) {\n const index = Math.min(count - 1, Math.floor((point.t - previousStart) / periodMs));\n previous[index] = (previous[index] ?? 0) + point.v;\n }\n }\n const labels = current.map((_, index) =>\n new Date(start + index * periodMs).toISOString().slice(5, 10));\n return { labels, current, previous };\n}\n\n/** MetricWidget-ready daily and weekly comparison windows. */\nexport function dashboardMetricData(\n points: Array<{ t: number; v: number }>,\n now: number,\n): DashboardMetricData {\n const DAY = 86_400_000;\n return {\n wow: periodSeries(points, now, 7, DAY),\n mom: periodSeries(points, now, 4, 7 * DAY),\n };\n}\n\n/** Annualized cents for a Stripe subscription: sum each item's\n * `unit_amount * quantity`, ×12 for monthly intervals. A yearly interval is\n * taken as-is. Returns 0 for a shape with no priced items. */\nexport function subAnnualCents(sub: Record<string, unknown>): number {\n const items = ((sub.items as { data?: Array<Record<string, unknown>> } | undefined)?.data ?? []);\n let cents = 0;\n for (const it of items) {\n const price = (it.price ?? {}) as { unit_amount?: number; recurring?: { interval?: string } };\n const per = (price.unit_amount ?? 0) * ((it.quantity as number) ?? 1);\n cents += price.recurring?.interval === \"month\" ? per * 12 : per;\n }\n return cents;\n}\n","// The Stripe payments provider — the only I/O half of payments. Talks to the\n// Stripe REST API over @odla-ai/stripe's fetch transport, and maps 1:1 onto the\n// membership-specific event normalization in ./payments. The worker\n// resolves secrets from the vault per request and constructs this; the routes own\n// every db write so idempotency stays at the db layer.\nimport { stripeRequest, verifyStripeSignature, type StripeRequestResult } from \"@odla-ai/stripe\";\nimport { normalizeWebhookEvent } from \"./payments\";\nimport type { StripeEvent, WebhookEvent } from \"./payments\";\n\n/** Inputs to create an application's founding-member subscription. */\nexport interface CreateSubscriptionInput {\n applicationId: string;\n groupId: string;\n email: string;\n name: string;\n priceId: string;\n existingCustomerId?: string;\n}\n\n/** The client secret to confirm card entry, plus the ids to persist. */\nexport interface CreateSubscriptionResult {\n customerId: string;\n subscriptionId: string;\n clientSecret: string;\n}\n\n/** The outcome of a full refund. */\nexport interface RefundResult {\n refundedCents: number | null;\n subscriptionCanceled: boolean;\n}\n\n/** The capabilities the payment routes depend on — Stripe is one impl. */\nexport interface PaymentsProvider {\n createSubscription(input: CreateSubscriptionInput): Promise<CreateSubscriptionResult>;\n ingestWebhook(\n rawBody: string,\n sigHeader: string,\n ): Promise<{ ok: true; eventId: string; event: WebhookEvent } | { ok: false; reason: \"bad_signature\" }>;\n refund(input: { customerId: string; subscriptionId: string }): Promise<RefundResult>;\n}\n\n/** The result of a Stripe Backend API call: ok + status + parsed JSON body. */\nexport type StripeResult = StripeRequestResult<Record<string, unknown>>;\n\n/** Call the Stripe Backend API (form-encoded, Bearer sk_). Exposed so the admin\n * billing/dashboard reads and the refund route share one Stripe client instead\n * of each re-deriving the auth + encoding. */\nexport async function stripeCall(\n sk: string,\n method: \"GET\" | \"POST\" | \"DELETE\",\n path: string,\n params?: Record<string, unknown>,\n idempotencyKey?: string,\n): Promise<StripeResult> {\n return stripeRequest(\n { secretKey: sk },\n method,\n path,\n params,\n idempotencyKey ? { idempotencyKey } : {},\n );\n}\n\nfunction fail(op: string, r: StripeResult): never {\n const err = new Error(`stripe ${op} failed: ${r.status}`) as Error & { code: string };\n err.code = \"stripe_error\";\n throw err;\n}\n\nfunction clientSecretOf(sub: Record<string, unknown>): string | undefined {\n const inv = sub.latest_invoice as Record<string, unknown> | undefined;\n const confirmation = inv?.confirmation_secret as Record<string, unknown> | undefined;\n const intent = inv?.payment_intent as Record<string, unknown> | undefined;\n const secret = confirmation?.client_secret ?? intent?.client_secret;\n return typeof secret === \"string\" ? secret : undefined;\n}\n\nfunction requireSecret(secretKey: string | undefined): string {\n if (!secretKey) {\n const err = new Error(\"stripe secret key missing\") as Error & { code: string };\n err.code = \"not_configured\";\n throw err;\n }\n return secretKey;\n}\n\n/** Build the Stripe provider. `secretKey` powers charging/refunds; `webhookSecret`\n * powers webhook ingest. Each is resolved from the vault per request, so the\n * webhook route can construct an ingest-only provider without the secret key. */\nexport function createStripeProvider(config: { secretKey?: string; webhookSecret?: string }): PaymentsProvider {\n const { secretKey, webhookSecret } = config;\n return {\n async createSubscription(input) {\n const sk = requireSecret(secretKey);\n const meta = { applicationId: input.applicationId, groupId: input.groupId, email: input.email };\n let customerId = input.existingCustomerId;\n if (!customerId) {\n const cust = await stripeCall(\n sk,\n \"POST\",\n \"/v1/customers\",\n { email: input.email, name: input.name, metadata: meta },\n `cus:${input.applicationId}`,\n );\n if (!cust.ok) fail(\"customer create\", cust);\n customerId = String(cust.body.id);\n }\n const sub = await stripeCall(\n sk,\n \"POST\",\n \"/v1/subscriptions\",\n {\n customer: customerId,\n \"items[0][price]\": input.priceId,\n payment_behavior: \"default_incomplete\",\n \"payment_settings[save_default_payment_method]\": \"on_subscription\",\n \"payment_settings[payment_method_types][0]\": \"card\",\n \"expand[0]\": \"latest_invoice.confirmation_secret\",\n metadata: meta,\n },\n // Hardening: one subscription per application, so a client\n // retry between create and the db write can't orphan a second one.\n `sub:${input.applicationId}`,\n );\n if (!sub.ok) fail(\"subscription create\", sub);\n const clientSecret = clientSecretOf(sub.body);\n if (!clientSecret) fail(\"subscription confirmation-secret missing\", sub);\n return { customerId, subscriptionId: String(sub.body.id), clientSecret };\n },\n\n async ingestWebhook(rawBody, sigHeader) {\n if (!webhookSecret || !(await verifyStripeSignature(rawBody, sigHeader, webhookSecret))) {\n return { ok: false, reason: \"bad_signature\" };\n }\n const event = JSON.parse(rawBody) as StripeEvent;\n return { ok: true, eventId: event.id, event: normalizeWebhookEvent(event) };\n },\n\n async refund(input) {\n const sk = requireSecret(secretKey);\n const charges = await stripeCall(sk, \"GET\", \"/v1/charges\", { customer: input.customerId, limit: 100 });\n if (!charges.ok) fail(\"charges list\", charges);\n const rows = (charges.body.data as Array<Record<string, unknown>> | undefined) ?? [];\n const paid = rows.filter((c) => c.status === \"succeeded\" && c.refunded !== true);\n const charge = paid[paid.length - 1]; // Stripe returns newest-first; refund the earliest.\n if (!charge) {\n const err = new Error(\"no paid charge to refund\") as Error & { code: string };\n err.code = \"no_charge\";\n throw err;\n }\n const refund = await stripeCall(sk, \"POST\", \"/v1/refunds\", { charge: String(charge.id) });\n if (!refund.ok) fail(\"refund\", refund);\n const cancel = await stripeCall(sk, \"DELETE\", `/v1/subscriptions/${input.subscriptionId}`);\n const amount = refund.body.amount;\n return { refundedCents: typeof amount === \"number\" ? amount : null, subscriptionCanceled: cancel.ok };\n },\n };\n}\n","// Apply-time account provisioning. When an application arrives, the worker mints\n// a Clerk invitation so the applicant gets a path into their member area — the\n// generalized server-side account step. Chapter calls the Clerk\n// Backend API directly over fetch (vault clerk_secret_key), mirroring\n// @odla-ai/auth-clerk's createInvitation but self-contained, so it never pulls the\n// auth-clerk UI package into the worker bundle. Best-effort at the call site: a\n// provisioning failure never fails the application.\n\n/** The outcome of a Clerk provisioning call. `existed` marks the heal case: Clerk\n * rejected it because the account/invitation is already there, which is the end\n * state we wanted anyway. */\nexport interface ClerkResult {\n ok: boolean;\n status: number;\n existed?: boolean;\n /** Set when an `existed` heal also refreshed the account's metadata. */\n refreshed?: boolean;\n}\n\n// Clerk answers 422 when the email already has a user (or a pending invitation).\n// For apply-time provisioning that's success, not failure — the account exists.\nconst heal = (status: number): ClerkResult =>\n status === 422 ? { ok: true, status, existed: true } : { ok: false, status };\n\n/** Inputs for a Clerk invitation. */\nexport interface ClerkInviteInput {\n email: string;\n /** Where the accept-invitation link lands (usually the member area). */\n redirectUrl?: string;\n /** Written to the invitation's `public_metadata`. Clerk application\n * invitations cannot carry private metadata, so never put applicant profile\n * fields here. Chapter completes that backend-only write after acceptance. */\n publicMetadata?: Record<string, unknown>;\n}\n\n/** Build the Clerk Backend API invitation request (path + JSON body). Pure, so\n * the wire shape is testable without a network call. */\nexport function clerkInviteRequest(input: ClerkInviteInput): { path: string; body: Record<string, unknown> } {\n return {\n path: \"/v1/invitations\",\n body: {\n email_address: input.email,\n notify: true,\n ...(input.redirectUrl ? { redirect_url: input.redirectUrl } : {}),\n ...(input.publicMetadata ? { public_metadata: input.publicMetadata } : {}),\n },\n };\n}\n\n/** POST the invitation to the Clerk Backend API. A repeat invite for an\n * already-invited email heals to `{ ok: true, existed: true }` rather than\n * reporting a failure the caller would have to special-case. */\nexport async function createClerkInvitation(\n secretKey: string,\n input: ClerkInviteInput,\n fetchImpl: typeof fetch = fetch,\n): Promise<ClerkResult> {\n const { path, body } = clerkInviteRequest(input);\n const res = await fetchImpl(`https://api.clerk.com${path}`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${secretKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return res.ok ? { ok: true, status: res.status } : heal(res.status);\n}\n\n/** Inputs for a server-side Clerk user create. */\nexport interface ClerkUserInput {\n email: string;\n firstName?: string;\n lastName?: string;\n /** Backend-authored, browser-readable claims such as `role`. */\n publicMetadata?: Record<string, unknown>;\n /** Backend-only account signals and profile data. */\n privateMetadata?: Record<string, unknown>;\n /** Optional metadata merge used only when create returns 422 for an existing\n * account. This lets migrations remove legacy keys without putting tombstone\n * values on a newly-created user. Defaults to the create metadata. */\n repairMetadata?: ClerkMetadataInput;\n}\n\n/** Build the Clerk Backend API user-create request. The account is created\n * passwordless (the member signs in via the site's Clerk flow), so join step 3\n * can say the account is ready — the \"create\" alternative to an invitation. */\nexport function clerkUserRequest(input: ClerkUserInput): { path: string; body: Record<string, unknown> } {\n return {\n path: \"/v1/users\",\n body: {\n email_address: [input.email],\n skip_password_requirement: true,\n ...(input.firstName ? { first_name: input.firstName } : {}),\n ...(input.lastName ? { last_name: input.lastName } : {}),\n ...(input.publicMetadata !== undefined ? { public_metadata: input.publicMetadata } : {}),\n ...(input.privateMetadata !== undefined ? { private_metadata: input.privateMetadata } : {}),\n },\n };\n}\n\n/** One merge-PATCH to the metadata fields Clerk exposes on its Backend API. */\nexport interface ClerkMetadataInput {\n publicMetadata?: Record<string, unknown>;\n privateMetadata?: Record<string, unknown>;\n}\n\n/** Merge metadata into an existing Clerk user. Nested `null` values remove old\n * keys, which Chapter uses to migrate its former public profile into private\n * metadata without disturbing the public `role` claim. */\nexport async function updateClerkUserMetadata(\n secretKey: string,\n userId: string,\n input: ClerkMetadataInput,\n fetchImpl: typeof fetch = fetch,\n): Promise<boolean> {\n const res = await fetchImpl(`https://api.clerk.com/v1/users/${encodeURIComponent(userId)}/metadata`, {\n method: \"PATCH\",\n headers: { authorization: `Bearer ${secretKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({\n ...(input.publicMetadata !== undefined ? { public_metadata: input.publicMetadata } : {}),\n ...(input.privateMetadata !== undefined ? { private_metadata: input.privateMetadata } : {}),\n }),\n });\n return res.ok;\n}\n\n/** Look a Clerk account up by email and merge its metadata.\n *\n * Returns `false` when no matching user can be resolved or Clerk rejects the\n * lookup or update. Chapter uses this for create-healing and invitation\n * adoption so a repeated application repairs the private account snapshot.\n */\nexport async function updateClerkUserMetadataByEmail(\n secretKey: string,\n email: string,\n input: ClerkMetadataInput,\n fetchImpl: typeof fetch = fetch,\n): Promise<boolean> {\n const auth = { authorization: `Bearer ${secretKey}` };\n const found = await fetchImpl(`https://api.clerk.com/v1/users?email_address=${encodeURIComponent(email)}&limit=1`, { headers: auth });\n if (!found.ok) return false;\n const users = (await found.json().catch(() => null)) as Array<{ id?: unknown }> | null;\n const id = Array.isArray(users) && typeof users[0]?.id === \"string\" ? users[0].id : undefined;\n if (!id) return false;\n return updateClerkUserMetadata(secretKey, id, input, fetchImpl);\n}\n\n/** Create the applicant's Clerk account server-side. A repeat for an email that\n * already has an account heals to `{ ok: true, existed: true }` — the account\n * exists, which is the state apply-time provisioning wanted — and refreshes\n * supplied public/private metadata on the existing account so a re-application\n * repairs a previously missed create (`refreshed: true`). */\nexport async function createClerkUser(\n secretKey: string,\n input: ClerkUserInput,\n fetchImpl: typeof fetch = fetch,\n): Promise<ClerkResult> {\n const { path, body } = clerkUserRequest(input);\n const res = await fetchImpl(`https://api.clerk.com${path}`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${secretKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (res.ok) return { ok: true, status: res.status };\n const healed = heal(res.status);\n const repair = input.repairMetadata ?? {\n ...(input.publicMetadata !== undefined ? { publicMetadata: input.publicMetadata } : {}),\n ...(input.privateMetadata !== undefined ? { privateMetadata: input.privateMetadata } : {}),\n };\n if (\n !healed.existed ||\n (repair.publicMetadata === undefined && repair.privateMetadata === undefined)\n ) return healed;\n const refreshed = await updateClerkUserMetadataByEmail(secretKey, input.email, {\n ...(repair.publicMetadata !== undefined ? { publicMetadata: repair.publicMetadata } : {}),\n ...(repair.privateMetadata !== undefined ? { privateMetadata: repair.privateMetadata } : {}),\n }, fetchImpl).catch(() => false);\n return { ...healed, refreshed };\n}\n","// The odla->Clerk write half: server-side Clerk role read/list/write, the gap\n// beside clerk.ts's create/invite/heal. Roles live in `public_metadata.role`; an\n// absent role means the lowest rung (\"provisional\") — chapter never writes it at\n// create. Account profile signals live in backend-only `private_metadata`; the\n// role write is a MERGE-PATCH of only `{ role }`, so it cannot clobber them.\n// Chapter calls the Clerk Backend API over fetch with the vault\n// `clerk_secret_key`.\n\nconst CLERK_API = \"https://api.clerk.com\";\nconst DEFAULT_ROLE = \"provisional\";\nconst PAGE = 100;\n\n/** A Clerk user as chapter's role layer sees it. `role` defaults to the lowest\n * rung when `public_metadata` carries none. Raw public/private metadata is\n * returned only from this backend helper; `profile` and `applicationId` are the\n * normalized Chapter-owned private signals. */\nexport interface ClerkUserRecord {\n id: string;\n email?: string;\n role: string;\n publicMetadata: Record<string, unknown>;\n privateMetadata: Record<string, unknown>;\n profile: Record<string, unknown>;\n applicationId?: string;\n}\n\n// The Clerk Backend API user object — only the fields chapter reads.\ninterface ClerkApiUser {\n id?: unknown;\n email_addresses?: Array<{ email_address?: unknown }>;\n public_metadata?: Record<string, unknown>;\n private_metadata?: Record<string, unknown>;\n}\n\nfunction toRecord(u: ClerkApiUser): ClerkUserRecord | null {\n if (typeof u.id !== \"string\") return null;\n const pm = (u.public_metadata ?? {}) as Record<string, unknown>;\n const privateMetadata = (u.private_metadata ?? {}) as Record<string, unknown>;\n const rawProfile = privateMetadata.profile;\n const profile = rawProfile && typeof rawProfile === \"object\" && !Array.isArray(rawProfile)\n ? rawProfile as Record<string, unknown>\n : {};\n const applicationId = typeof privateMetadata.applicationId === \"string\"\n ? privateMetadata.applicationId\n : undefined;\n const role = typeof pm.role === \"string\" && pm.role ? pm.role : DEFAULT_ROLE;\n const email = u.email_addresses?.[0]?.email_address;\n return {\n id: u.id,\n email: typeof email === \"string\" ? email : undefined,\n role,\n publicMetadata: pm,\n privateMetadata,\n profile,\n ...(applicationId ? { applicationId } : {}),\n };\n}\n\nasync function clerkGet(path: string, secretKey: string, fetchImpl: typeof fetch): Promise<unknown> {\n const res = await fetchImpl(`${CLERK_API}${path}`, { headers: { authorization: `Bearer ${secretKey}` } });\n if (!res.ok) throw new Error(`clerk GET ${path} → ${res.status}`);\n return res.json();\n}\n\n/** Look a Clerk user up by email. `null` when no such user — or when the lookup\n * fails (a role gate treats an unresolvable user as absent, matching the site's\n * own fallback). Role defaults to provisional when unset. */\nexport async function clerkGetUserByEmail(secretKey: string, email: string, fetchImpl: typeof fetch = fetch): Promise<ClerkUserRecord | null> {\n const data = await clerkGet(`/v1/users?email_address=${encodeURIComponent(email)}&limit=1`, secretKey, fetchImpl).catch(() => null);\n const user = Array.isArray(data) ? (data[0] as ClerkApiUser | undefined) : undefined;\n return user ? toRecord(user) : null;\n}\n\n/** Fetch a Clerk user by id, for role-change gating. `null` when missing or on a\n * failed lookup. Role defaults to provisional when unset. */\nexport async function clerkGetUser(secretKey: string, id: string, fetchImpl: typeof fetch = fetch): Promise<ClerkUserRecord | null> {\n const data = await clerkGet(`/v1/users/${encodeURIComponent(id)}`, secretKey, fetchImpl).catch(() => null);\n return data ? toRecord(data as ClerkApiUser) : null;\n}\n\n/** List ALL Clerk users with their roles, auto-paginating. A membership community\n * outgrows one page, and a fixed `limit=100` would silently drop members from the\n * admin roster with no error — so this pages (offset in steps of {@link PAGE})\n * until a short page. A page fetch that fails THROWS rather than returning a\n * partial list, so the caller never mistakes a truncated roster for the whole. */\nexport async function clerkListUsers(secretKey: string, fetchImpl: typeof fetch = fetch): Promise<ClerkUserRecord[]> {\n const out: ClerkUserRecord[] = [];\n for (let offset = 0; ; offset += PAGE) {\n const data = await clerkGet(`/v1/users?limit=${PAGE}&offset=${offset}`, secretKey, fetchImpl);\n const page = Array.isArray(data) ? (data as ClerkApiUser[]) : [];\n for (const u of page) {\n const record = toRecord(u);\n if (record) out.push(record);\n }\n if (page.length < PAGE) break;\n }\n return out;\n}\n\n/** Write a user's role: a MERGE-PATCH of only `{ role }` on `public_metadata`.\n * The backend-only profile lives in `private_metadata`, so the two signals\n * cannot overwrite each other. Returns whether the role write stuck. */\nexport async function clerkSetRole(secretKey: string, id: string, role: string, fetchImpl: typeof fetch = fetch): Promise<boolean> {\n const res = await fetchImpl(`${CLERK_API}/v1/users/${encodeURIComponent(id)}/metadata`, {\n method: \"PATCH\",\n headers: { authorization: `Bearer ${secretKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({ public_metadata: { role } }),\n });\n return res.ok;\n}\n","// The Clerk capability descriptor: documentation-as-data — \"what settings/secrets\n// does turning Clerk on need?\", \"what must the CLI provision?\", and \"what data\n// syncs, in which direction?\". It lives here (not in the browser package\n// @odla-ai/auth-clerk) because the sync contract is implemented by odla-db + the\n// platform webhook (provider->odla) and by chapter's clerk.ts (odla->provider),\n// neither of which is browser code. auth-clerk stays a pure UI package. Data only:\n// it describes the capability, it performs none of it.\n\n/** Which auth mode a secret is required for: `\"client\"` (publishable key only) or\n * `\"full\"` (server-side profile/role reads + writes, needing the vault secret). */\nexport type SecretMode = \"client\" | \"full\";\n\n/** A configuration value the capability needs (e.g. the publishable key). */\nexport interface IntegrationSetting {\n key: string;\n description: string;\n /** Safe to ship to the browser? (publishable keys are; secrets are not). */\n public: boolean;\n /** Expected value shape, e.g. a \"pk_\" prefix. */\n pattern?: string;\n /** Stored per environment (dev/prod)? */\n perEnv: boolean;\n /** Where the value is stored and read from. */\n source: string;\n}\n\n/**\n * A secret the capability needs, held in the tenant vault.\n *\n * Structurally the odla CLI's `IntegrationSecret`: `name` is the vault name\n * byte-for-byte, so `odla-ai doctor`, `odla-ai secrets status`, and the\n * repo's `check:secrets` gate can hold this declaration against the name the\n * platform actually reads. `mode` is chapter's own addition and the CLI\n * ignores it.\n */\nexport interface IntegrationSecret {\n /** Vault name, exactly as `odla-ai secrets set <name>` writes it. */\n name: string;\n description: string;\n pattern?: string;\n /** Auth mode that requires this secret (\"full\" pulls user profiles). */\n mode: SecretMode;\n /** Whether the capability is broken without it. Both Clerk secrets are\n * needed only by auth mode \"full\", so both are optional. */\n required?: boolean;\n}\n\n/** One data-sync contract. A capability may declare several (e.g. an inbound\n * webhook mirror AND an outbound write), so {@link IntegrationDescriptor.syncs}\n * is a list. The mechanism is declared, not reimplemented here. */\nexport interface IntegrationSync {\n engine: string;\n direction: \"provider->odla\" | \"odla->provider\" | \"bidirectional\";\n entity: string;\n fields: string[];\n webhook?: string;\n onDelete?: string;\n}\n\n/** The provisioning split: human, CLI, and doctor-assertable steps. */\nexport interface IntegrationProvision {\n /** Steps a human performs (out-of-band, e.g. in the Clerk dashboard). */\n human: string[];\n /** Steps the odla CLI automates. */\n cli: string[];\n /** Checks `odla doctor` should assert. */\n doctor: string[];\n}\n\n/** Documentation-as-data for a provider capability, consumed by the odla CLI,\n * `odla doctor`, and the docs. */\nexport interface IntegrationDescriptor {\n id: string;\n title: string;\n npm: string;\n settings: IntegrationSetting[];\n secrets: IntegrationSecret[];\n /** Every data-sync contract the capability declares, each with its direction. */\n syncs: IntegrationSync[];\n provision: IntegrationProvision;\n}\n\n/**\n * The concrete {@link IntegrationDescriptor} for the Clerk capability. Declares\n * the one public `setting` (the `pk_*` publishable key, served to the SPA), the\n * `secrets` auth mode `\"full\"` needs in the tenant vault, BOTH sync directions —\n * the inbound `$users` webhook mirror (`provider->odla`) and the outbound\n * public role/private profile write via `clerk_secret_key` (`odla->provider`,\n * chapter's `clerk.ts`) — and the `provision` split. Data only; it performs\n * none of it.\n */\nexport const clerkIntegration: IntegrationDescriptor = {\n id: \"clerk\",\n title: \"Clerk end-user auth\",\n npm: \"@odla-ai/chapter\",\n settings: [\n {\n key: \"publishableKey\",\n description: \"Clerk publishable key (pk_*). Public by design; served to the SPA (loads clerk-js from Clerk's CDN via @odla-ai/auth-clerk).\",\n public: true,\n pattern: \"pk_\",\n perEnv: true,\n source: \"apps-registry auth[env].publishableKey (from odla.config.mjs auth.clerk.<env>)\",\n },\n ],\n secrets: [\n {\n // odla-db reads this exact name (CLERK_WEBHOOK_SECRET_NAME in the\n // platform's clerk-webhook.ts); it is also what `odla-ai secrets set`\n // writes. It read \"CLERK_WEBHOOK_SECRET\" until 0.30.0, which sent\n // adopters to store the value under a name nothing looks up.\n name: \"clerk_webhook_secret\",\n description: \"Svix signing secret for Clerk user webhooks — verifies $users sync events.\",\n pattern: \"whsec_\",\n mode: \"full\",\n required: false,\n },\n {\n name: \"clerk_secret_key\",\n description: \"Clerk backend key (sk_*) — powers account creation, the public role claim, and backend-only private profile signals; it also lets odla-db resolve user email/name via the Clerk API.\",\n pattern: \"sk_\",\n mode: \"full\",\n required: false,\n },\n ],\n syncs: [\n {\n engine: \"@odla-ai/db $users (Clerk webhook -> tenant graph)\",\n direction: \"provider->odla\",\n entity: \"$users\",\n // Matches the webhook mapper: the mirror carries id + primary email + name + avatar.\n fields: [\"id\", \"email\", \"name\", \"imageUrl\"],\n webhook: \"whsec_ (svix-signed)\",\n onDelete: \"tombstone (never row-delete)\",\n },\n {\n engine: \"@odla-ai/chapter clerk.ts (Clerk Backend API via vault clerk_secret_key)\",\n direction: \"odla->provider\",\n entity: \"clerk user\",\n // Separate metadata fields so a public role write cannot expose or\n // clobber backend-only account/profile signals.\n fields: [\n \"public_metadata.role\",\n \"private_metadata.applicationId\",\n \"private_metadata.profile\",\n ],\n onDelete: \"n/a (writes only)\",\n },\n ],\n provision: {\n human: [\n \"Run `npx clerk auth login` — the one interactive step; the agent then creates + configures the Clerk app with the Clerk CLI (no pk_ to hand-paste).\",\n 'For auth mode \"full\": create the Clerk user-sync webhook and store its whsec_, plus the sk_ as clerk_secret_key, in the tenant vault (Studio, write-only).',\n ],\n cli: [\n \"Clerk CLI (`npx clerk apps create/link/config patch`) creates + configures the instance and pulls the pk_.\",\n \"odla `provision` records it: setAuth(env, publishableKey) -> apps-registry (issuer/JWKS derived from the key).\",\n ],\n doctor: [\n \"registry auth[env] present when the app mounts <SignIn>?\",\n 'auth mode \"full\" => whsec_ and clerk_secret_key present in the tenant vault?',\n ],\n },\n};\n","// The member session — what GET /api/me returns to a signed-in applicant/member.\n// Ported from the reference application's summary + /api/me reconciliation. The\n// SHAPING is pure and package-enforced so no site re-derives it; the worker owns\n// only the I/O around it (locating the application by email, reconciling the\n// meeting against the calendar) and hands the resolved rows here.\n//\n// Two invariants live here, not in a site:\n// - `paid` is DERIVED, never a stored flag: a subscription exists and the\n// application wasn't refunded. Sites can't drift a stale boolean out of sync\n// with Stripe.\n// - the live meeting row wins: its startAt/meetUrl/timezone override whatever\n// the application row cached, and a non-scheduled meeting (a cancellation\n// adopted from the calendar) forces meetingAt back to null.\n\n/** An application row, as far as the session cares about it. */\nexport interface ApplicationRecord {\n id: string;\n firstName?: string | null;\n lastName?: string | null;\n email?: string | null;\n status: string;\n meetingAt?: number | null;\n meetingLink?: string | null;\n createdAt?: number | null;\n stripeSubscriptionId?: string | null;\n renewalAt?: number | null;\n canceled?: boolean;\n tierId?: string | null;\n}\n\n/** The reconciled meeting row (already adopted against the calendar), or null. */\nexport interface MeetingRecord {\n status: string;\n startAt?: number | null;\n meetUrl?: string | null;\n timezone?: string | null;\n}\n\n/** The stable, non-meeting fields of an application (safe to expose to its own\n * owner). */\nexport interface ApplicationSummary {\n id: string;\n firstName: string | null;\n lastName: string | null;\n email: string | null;\n status: string;\n createdAt: number | null;\n meetingLink: string | null;\n paid: boolean;\n renewalAt: number | null;\n canceled: boolean;\n /** Server-authoritative membership tier selected on this application. */\n tierId: string | null;\n}\n\n/** A summary plus the reconciled meeting fields — the `application` the member\n * area renders. */\nexport interface MemberApplication extends ApplicationSummary {\n meetingAt: number | null;\n meetUrl: string | null;\n timezone: string;\n}\n\n/** The full GET /api/me payload for a signed-in user. */\nexport interface MemberSession {\n userId: string;\n email: string | null;\n role: string;\n superAdmin: boolean;\n application: MemberApplication | null;\n}\n\n/** Derive the summary fields from an application row. `paid` is computed, not\n * read, so it can never contradict Stripe. */\nexport function applicationSummary(app: ApplicationRecord): ApplicationSummary {\n return {\n id: app.id,\n firstName: app.firstName ?? null,\n lastName: app.lastName ?? null,\n email: app.email ?? null,\n status: app.status,\n createdAt: app.createdAt ?? null,\n meetingLink: app.meetingLink ?? null,\n paid: Boolean(app.stripeSubscriptionId) && app.status !== \"refunded\",\n renewalAt: app.renewalAt ?? null,\n canceled: app.canceled === true,\n tierId: app.tierId ?? null,\n };\n}\n\n/** Fold a (possibly absent, already-reconciled) meeting into the application the\n * member area renders. The live meeting overrides the application's cached\n * meeting fields; a non-`scheduled` meeting clears the booking. */\nexport function memberApplication(\n app: ApplicationRecord,\n meeting: MeetingRecord | null | undefined,\n defaultTimezone: string,\n): MemberApplication {\n const summary = applicationSummary(app);\n let meetingAt = app.meetingAt ?? null;\n let meetUrl: string | null = null;\n let timezone = defaultTimezone;\n if (meeting) {\n timezone = meeting.timezone ?? timezone;\n if (meeting.status === \"scheduled\") {\n meetingAt = meeting.startAt ?? null;\n meetUrl = meeting.meetUrl ?? null;\n } else {\n meetingAt = null;\n }\n }\n return { ...summary, meetingAt, meetUrl, timezone };\n}\n\n/** Identity of the signed-in user, from the verified session. */\nexport interface SessionUser {\n userId: string;\n email?: string | null;\n role: string;\n}\n\n/** Assemble the GET /api/me payload. `application` is null when the user has no\n * application on file (an admin who never applied, or a brand-new account). */\nexport function memberSession(\n user: SessionUser,\n opts: { application: MemberApplication | null; superAdmin: boolean },\n): MemberSession {\n return {\n userId: user.userId,\n email: user.email ?? null,\n role: user.role,\n superAdmin: opts.superAdmin,\n application: opts.application,\n };\n}\n","// Brand tokens (H4). defineChapter accepts a `brand` block; this turns it into a\n// `:root { --…: … }` CSS block, so a chapter re-skins the WHOLE UI — the\n// @odla-ai/ui components, the admin shell, and the member islands, which all read\n// --ui-* design tokens — from one config instead of hand-writing inline CSS.\n//\n// Pure string generation, so it is unit-testable and can be emitted at\n// build/SSR time into the page <head> (no flash of unstyled content), or via the\n// <BrandStyle> component from @odla-ai/chapter/ui.\nimport type { ChapterBrand, ChapterBrandTokens } from \"./types\";\n\n// A palette entry is either a direct custom property (already `--…`, e.g.\n// `--ui-accent` to retheme components) or a bare name we expose as `--<name>`\n// (e.g. `moss` → `--moss`, for a site to reference in its own CSS).\nfunction paletteVar(key: string): string {\n return key.startsWith(\"--\") ? key : `--${key}`;\n}\n\n// Strip characters that could break out of a `--var: value;` declaration or the\n// surrounding <style>. Brand config is trusted author input, so this is a\n// belt-and-suspenders guard, not a security boundary.\nfunction cleanValue(value: string): string {\n return value.replace(/[<>{};]/g, \"\").trim();\n}\n\nfunction paletteDecls(palette: Record<string, string> | undefined): string[] {\n const decls: string[] = [];\n for (const [key, value] of Object.entries(palette ?? {})) {\n if (typeof value === \"string\" && value.trim()) decls.push(`${paletteVar(key)}: ${cleanValue(value)};`);\n }\n return decls;\n}\n\nconst TOKEN_VARS: Record<keyof ChapterBrandTokens, string> = {\n background: \"--ui-bg\",\n surface: \"--ui-surface\",\n surface2: \"--ui-surface-2\",\n text: \"--ui-text\",\n textMuted: \"--ui-text-muted\",\n textFaint: \"--ui-text-faint\",\n border: \"--ui-border\",\n borderStrong: \"--ui-border-strong\",\n accent: \"--ui-accent\",\n accentStrong: \"--ui-accent-strong\",\n accentSoft: \"--ui-accent-soft\",\n onAccent: \"--ui-on-accent\",\n good: \"--ui-good\",\n warn: \"--ui-warn\",\n danger: \"--ui-danger\",\n chart1: \"--ui-chart-1\",\n chart2: \"--ui-chart-2\",\n chart3: \"--ui-chart-3\",\n chart4: \"--ui-chart-4\",\n chart5: \"--ui-chart-5\",\n chart6: \"--ui-chart-6\",\n chartPositive: \"--ui-chart-pos\",\n chartNegative: \"--ui-chart-neg\",\n contentWidth: \"--ui-content-width\",\n panelRadius: \"--ui-radius-lg\",\n panelShadow: \"--ui-shadow\",\n masterDetailColumns: \"--ui-master-detail-columns\",\n masterDetailMinHeight: \"--ui-master-detail-min-height\",\n pagePadding: \"--chapter-admin-page-padding\",\n workspacePadding: \"--chapter-admin-workspace-padding\",\n};\n\nfunction semanticDecls(tokens: ChapterBrandTokens | undefined): string[] {\n return Object.entries(tokens ?? {}).flatMap(([key, value]) =>\n typeof value === \"string\" && value.trim()\n ? [`${TOKEN_VARS[key as keyof ChapterBrandTokens]}: ${cleanValue(value)};`]\n : [],\n );\n}\n\n/**\n * Build the CSS that maps a chapter's brand onto the design tokens the UI reads:\n * each `palette` entry becomes a custom property (light, and dark unless\n * `paletteDark` overrides), and `fonts` (display/body/numeral) map to\n * `--ui-font-display` / `--ui-font-sans` / `--ui-font-numeral`. The dark block is\n * emitted under both `:root[data-theme=\"dark\"]` (the odla-ui theme toggle) and\n * `@media (prefers-color-scheme: dark)`. Returns \"\" when there is nothing to\n * theme. These are brand OVERRIDES on top of a base theme — they do not replace\n * the theme layer the components need (see {@link brandTokens} usage in the docs).\n */\nexport function brandTokens(\n brand: ChapterBrand | undefined,\n options: { selector?: string } = {},\n): string {\n if (!brand) return \"\";\n const light = [...paletteDecls(brand.palette), ...semanticDecls(brand.tokens)];\n const fonts = brand.fonts;\n if (fonts?.display) light.push(`--ui-font-display: ${cleanValue(fonts.display)};`);\n if (fonts?.body) light.push(`--ui-font-sans: ${cleanValue(fonts.body)};`);\n if (fonts?.numeral) light.push(`--ui-font-numeral: ${cleanValue(fonts.numeral)};`);\n const dark = [...paletteDecls(brand.paletteDark), ...semanticDecls(brand.tokensDark)];\n const invert = paletteDecls(brand.paletteInvert);\n const selector = options.selector ?? \":root\";\n const darkSelector = selector === \":root\" ? ':root[data-theme=\"dark\"]' : `${selector}[data-theme=\"dark\"]`;\n const systemSelector = selector === \":root\"\n ? ':root:not([data-theme=\"light\"])'\n : `${selector}:not([data-theme=\"light\"])`;\n\n let css = light.length ? `${selector} {\\n ${light.join(\"\\n \")}\\n}\\n` : \"\";\n if (dark.length) {\n const block = `{\\n ${dark.join(\"\\n \")}\\n}`;\n css += `${darkSelector} ${block}\\n@media (prefers-color-scheme: dark) {\\n ${systemSelector} ${block}\\n}\\n`;\n }\n if (invert.length) {\n const invertSelector = selector === \":root\"\n ? \".ui-invert\"\n : `${selector}.ui-invert, ${selector} .ui-invert`;\n css += `${invertSelector} {\\n color-scheme: dark;\\n ${invert.join(\"\\n \")}\\n}\\n`;\n }\n return css;\n}\n\n/** Structural output accepted from `@odla-ai/brand`'s pure token compiler. */\nexport interface CompiledChapterBrandTokens {\n light: Record<string, string>;\n dark: Record<string, string>;\n}\n\n/**\n * Turn a complete compiled token pair into Chapter's brand contract without\n * coupling Chapter's runtime to the brand-book/agent package. Explicit values in\n * `base` win, so a host can make final per-site adjustments after compilation.\n */\nexport function chapterBrandFromTokens(\n compiled: CompiledChapterBrandTokens,\n base: ChapterBrand = {},\n): ChapterBrand {\n return {\n ...base,\n palette: { ...compiled.light, ...base.palette },\n paletteDark: { ...compiled.dark, ...base.paletteDark },\n paletteInvert: { ...compiled.dark, ...base.paletteInvert },\n };\n}\n","// The Google → chapter half of the bidirectional calendar sync. Booking writes\n// events TO the platform calendar (0.4.0's create/reschedule); this ADOPTS edits\n// FROM it: when the owner moves or cancels the intro call directly in Google,\n// reconcile mirrors that onto our canonical `meetings` row and the `application`\n// projection. Chapter never calls Google — the worker reads live events through\n// @odla-ai/calendar's upcoming() (platform-brokered) and applies the ops this\n// returns. Pure + testable; adoption policy (owner edits win) matches the shipped\n// original production worker.\n\n/** A `meetings` row, as far as reconciliation cares. */\nexport interface MeetingForReconcile {\n id: string;\n applicationId: string;\n googleEventId?: string | null;\n status: string;\n startAt?: number | null;\n endAt?: number | null;\n}\n\n/** One live calendar event (a subset of @odla-ai/calendar's Booking). */\nexport interface LiveEvent {\n eventId: string;\n status?: string;\n startAt?: number;\n endAt?: number;\n}\n\n/** An adopt decision: mirror a Google move/cancel onto our rows. */\nexport interface ReconcileDecision {\n meetingId: string;\n applicationId: string;\n kind: \"cancelled\" | \"moved\";\n /** Attrs to write onto the `meetings` row. */\n meetingPatch: Record<string, unknown>;\n /** Attrs to write onto the `applications` row (the projection). */\n applicationPatch: Record<string, unknown>;\n}\n\n/** Meetings still worth reconciling: a scheduled booking with a Google event that\n * starts in the future (or within the last hour, to catch a just-passed edit). */\nexport function isReconcilable(meeting: MeetingForReconcile, now: number): boolean {\n return meeting.status === \"scheduled\" && Boolean(meeting.googleEventId) && (meeting.startAt ?? 0) > now - 3_600_000;\n}\n\n/**\n * Diff canonical `meetings` against the live calendar events and return the adopt\n * decisions — only for meetings that actually changed (a still-matching meeting\n * is omitted). A meeting whose event vanished or is `cancelled` in Google is\n * adopted as cancelled (application `meetingAt` zeroed — 0 means \"was booked,\n * then cancelled\"); a meeting whose event moved adopts the new window (duration\n * preserved when the event omits `endAt`).\n */\nexport function reconcileMeetings(\n meetings: readonly MeetingForReconcile[],\n events: readonly LiveEvent[],\n now: number,\n): ReconcileDecision[] {\n const byEvent = new Map(events.map((e) => [e.eventId, e]));\n const decisions: ReconcileDecision[] = [];\n for (const m of meetings) {\n if (!isReconcilable(m, now) || !m.googleEventId) continue;\n const g = byEvent.get(m.googleEventId);\n if (!g || g.status === \"cancelled\") {\n decisions.push({\n meetingId: m.id,\n applicationId: m.applicationId,\n kind: \"cancelled\",\n meetingPatch: { status: \"cancelled\", drift: \"none\", adoptedFromGoogleAt: now },\n applicationPatch: { meetingAt: 0, meetingLink: \"\" },\n });\n } else if (g.startAt !== undefined && g.startAt !== m.startAt) {\n const duration = (m.endAt ?? 0) - (m.startAt ?? 0);\n decisions.push({\n meetingId: m.id,\n applicationId: m.applicationId,\n kind: \"moved\",\n meetingPatch: { startAt: g.startAt, endAt: g.endAt ?? g.startAt + duration, drift: \"none\", adoptedFromGoogleAt: now },\n applicationPatch: { meetingAt: g.startAt },\n });\n }\n }\n return decisions;\n}\n","// Scheduling core — config resolution + the booking invariants, ported from the\n// proven production worker. Everything here is PURE (no @odla-ai/calendar, no\n// db), so the correctness properties are unit-testable and package-enforced; the\n// worker route owns only the I/O (FreeBusy, computeBookableSlots, calendar\n// create/reschedule, the db writes) and calls these.\n//\n// Package-enforced invariants:\n// - the `meetings` row is canonical; applications.meetingAt and the calendar\n// event are projections written from it.\n// - one intro event per application, forever: a rebooking RESCHEDULES the\n// existing event (preserving its Meet link + invite thread), never creates a\n// second — see {@link bookingDecision} + {@link introIdempotencyKey}.\n// - status never moves backward on booking; you can only book from a pipeline\n// stage in `bookableFrom` — see `canBook` in ./pipeline + applicationBookingUpdate.\n// - endAt is always derived server-side, never client-supplied — see\n// {@link endForSlot}.\nimport type { ChapterScheduling } from \"./types\";\n\n/** A fully-resolved scheduling config (every field present). */\nexport interface ResolvedScheduling {\n slotMinutes: number;\n days: readonly number[];\n startHour: number;\n endHour: number;\n timezone: string;\n minNoticeHours: number;\n windowDays: number;\n summaryTemplate: string;\n}\n\n/** Proven defaults: 45-minute weekday slots, 9–5 Pacific, 24h notice,\n * a 14-day window. The summary is generic (a chapter's group seed supplies a\n * name-branded one). */\nexport const SCHEDULING_DEFAULTS: ResolvedScheduling = {\n slotMinutes: 45,\n days: [1, 2, 3, 4, 5],\n startHour: 9,\n endHour: 17,\n timezone: \"America/Los_Angeles\",\n minNoticeHours: 24,\n windowDays: 14,\n summaryTemplate: \"Introduction call with {{firstName}} {{lastName}}\",\n};\n\nfunction isValidTimeZone(tz: string): boolean {\n try {\n new Intl.DateTimeFormat(undefined, { timeZone: tz });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve a group's scheduling config against the defaults, validating every\n * bound at config-write time (throws on a bad config, so a\n * misconfiguration surfaces immediately rather than yielding empty slots).\n * `windowDays` is capped at 62 because Google FreeBusy is.\n */\nexport function resolveScheduling(config?: ChapterScheduling): ResolvedScheduling {\n const result = validateScheduling(config);\n if (result.ok) return result.value;\n const detail = Object.entries(result.errors)\n .map(([field, message]) => `${field}: ${message}`)\n .join(\" \");\n throw new Error(`scheduling: ${detail}`);\n}\n\n/** Validation messages keyed by form field. */\nexport type SchedulingErrors = Record<string, string>;\n\n/**\n * Validate a scheduling config field by field, collecting owner-readable messages\n * rather than throwing on the first problem. An admin settings form needs to say\n * *which* field is wrong and why — \"pick at least one day\" beats a stack trace —\n * so the admin route returns these directly. {@link resolveScheduling} is the\n * throwing wrapper for internal/config-time use.\n */\nexport function validateScheduling(\n config?: ChapterScheduling,\n): { ok: true; value: ResolvedScheduling } | { ok: false; errors: SchedulingErrors } {\n const d = config ?? {};\n const c: ResolvedScheduling = {\n slotMinutes: d.slotMinutes ?? SCHEDULING_DEFAULTS.slotMinutes,\n days: d.days ?? SCHEDULING_DEFAULTS.days,\n startHour: d.startHour ?? SCHEDULING_DEFAULTS.startHour,\n endHour: d.endHour ?? SCHEDULING_DEFAULTS.endHour,\n timezone: d.timezone ?? SCHEDULING_DEFAULTS.timezone,\n minNoticeHours: d.minNoticeHours ?? SCHEDULING_DEFAULTS.minNoticeHours,\n windowDays: d.windowDays ?? SCHEDULING_DEFAULTS.windowDays,\n summaryTemplate: d.summaryTemplate ?? SCHEDULING_DEFAULTS.summaryTemplate,\n };\n const errors: SchedulingErrors = {};\n if (!(c.slotMinutes >= 15 && c.slotMinutes <= 240)) {\n errors.slotMinutes = \"Slot length must be between 15 and 240 minutes.\";\n }\n if (!(c.windowDays >= 1 && c.windowDays <= 62)) {\n errors.windowDays = \"Booking window must be between 1 and 62 days (the calendar caps look-ahead at 62).\";\n }\n if (!(c.minNoticeHours >= 0 && c.minNoticeHours <= 336)) {\n errors.minNoticeHours = \"Minimum notice must be between 0 and 336 hours.\";\n }\n if (!(c.startHour >= 0 && c.startHour < c.endHour && c.endHour <= 24)) {\n errors.hours = \"Hours must satisfy 0 ≤ start < end ≤ 24.\";\n }\n const days = [...c.days];\n if (!days.length) errors.days = \"Pick at least one day.\";\n else if (!days.every((n) => Number.isInteger(n) && n >= 0 && n <= 6)) {\n errors.days = \"Days must be weekday numbers, 0 (Sunday) through 6 (Saturday).\";\n }\n if (typeof c.timezone !== \"string\" || !isValidTimeZone(c.timezone)) {\n errors.timezone = `\"${String(c.timezone)}\" is not a valid IANA timezone (for example \"America/Los_Angeles\").`;\n }\n if (typeof c.summaryTemplate !== \"string\") errors.summaryTemplate = \"Calendar summary template must be text.\";\n return Object.keys(errors).length > 0 ? { ok: false, errors } : { ok: true, value: { ...c, days } };\n}\n\n/** Statuses a member may book/reschedule from (early pipeline only). */\n// Booking eligibility is answered by the configured pipeline — canBook(status,\n// pipeline) in ./pipeline — not a hardcoded status list, so a chapter that\n// customizes its stages gets one consistent answer.\n\n/** The availability window: `[now, now + windowDays]` in epoch ms. */\nexport function slotWindow(now: number, windowDays: number): { from: number; to: number } {\n return { from: now, to: now + windowDays * 86_400_000 };\n}\n\n/** The slot's end instant, always derived from its start (never client-supplied). */\nexport function endForSlot(startAt: number, slotMinutes: number): number {\n return startAt + slotMinutes * 60_000;\n}\n\n/** Double-book pre-check: the requested start must land exactly on a currently\n * bookable slot boundary. */\nexport function isSlotAvailable(slots: readonly { startAt: number }[], startAt: number): boolean {\n return slots.some((s) => s.startAt === startAt);\n}\n\n/** Render a meeting summary from its template (`{{firstName}}`/`{{lastName}}`). */\nexport function renderSummary(template: string, app: { firstName?: string | null; lastName?: string | null }): string {\n return template.replace(\"{{firstName}}\", app.firstName ?? \"\").replace(\"{{lastName}}\", app.lastName ?? \"\");\n}\n\n/** The prior scheduled meeting for an application, as far as booking cares. */\nexport interface ExistingMeeting {\n id: string;\n googleEventId?: string | null;\n meetUrl?: string | null;\n htmlLink?: string | null;\n}\n\n/** Decide reschedule-vs-create: reschedule iff there's an existing event to move,\n * so the Meet link + invite thread survive and no second event is minted. */\nexport function bookingDecision(existing: ExistingMeeting | null | undefined): { reschedule: boolean; eventId: string | null } {\n const eventId = existing?.googleEventId ?? null;\n return { reschedule: Boolean(eventId), eventId };\n}\n\n/** The create idempotency key — one intro event per application, forever, so a\n * retried create returns the same booking rather than a duplicate. */\nexport function introIdempotencyKey(applicationId: string): string {\n return `application:${applicationId}:intro`;\n}\n\n/** The canonical `meetings` row for a first booking. A `type` (not `interface`)\n * so it stays assignable to a db op's `attrs` (Record<string, unknown>). */\nexport type NewMeetingRow = {\n id: string;\n applicationId: string;\n groupId: string;\n startAt: number;\n endAt: number;\n timezone: string;\n status: \"scheduled\";\n googleEventId: string;\n meetUrl?: string;\n htmlLink?: string;\n drift: \"none\";\n createdAt: number;\n};\n\n/** Build the new `meetings` row after the calendar created the event. Optional\n * scalars are omitted (never null), per the odla-db porting rule. */\nexport function meetingCreateRow(i: {\n meetingId: string;\n applicationId: string;\n groupId: string;\n startAt: number;\n endAt: number;\n timezone: string;\n googleEventId: string;\n meetUrl?: string | null;\n htmlLink?: string | null;\n createdAt: number;\n}): NewMeetingRow {\n return {\n id: i.meetingId,\n applicationId: i.applicationId,\n groupId: i.groupId,\n startAt: i.startAt,\n endAt: i.endAt,\n timezone: i.timezone,\n status: \"scheduled\",\n googleEventId: i.googleEventId,\n ...(i.meetUrl ? { meetUrl: i.meetUrl } : {}),\n ...(i.htmlLink ? { htmlLink: i.htmlLink } : {}),\n drift: \"none\",\n createdAt: i.createdAt,\n };\n}\n\n/** The `meetings`-row patch for a reschedule (same row id, moved in place). */\nexport type MeetingReschedulePatch = {\n startAt: number;\n endAt: number;\n drift: \"none\";\n};\n\n/** Patch to move an existing meeting to a new window. */\nexport function meetingRescheduleUpdate(startAt: number, endAt: number): MeetingReschedulePatch {\n return { startAt, endAt, drift: \"none\" };\n}\n\n/** The `applications`-row patch after a booking. */\nexport type ApplicationBookingPatch = {\n meetingAt: number;\n meetingLink?: string;\n status?: \"call_scheduled\";\n};\n\n/** Project the booking onto the application row: cache the time, adopt the\n * calendar link if any, and advance the status to `call_scheduled` unless it is\n * already there (never backward). */\nexport function applicationBookingUpdate(\n currentStatus: string,\n startAt: number,\n htmlLink?: string | null,\n): ApplicationBookingPatch {\n return {\n meetingAt: startAt,\n ...(htmlLink ? { meetingLink: htmlLink } : {}),\n ...(currentStatus !== \"call_scheduled\" ? { status: \"call_scheduled\" as const } : {}),\n };\n}\n","// Reading tiers out of the database. Kept apart from tiers.ts so the decision\n// logic there stays pure and directly testable, and apart from the route\n// modules so both the join config and the checkout resolve tiers identically —\n// a page that offers a tier the checkout would refuse is the bug this prevents.\nimport type { ChapterDb } from \"./types\";\nimport { offerableTiers, resolveTiers, type ChapterTier, type TierGroup } from \"./tiers\";\n\n/** A `groups` row as the tier loader needs it. */\nexport type TierGroupRow = TierGroup & { id?: string };\n\nfunction rowToTier(row: Record<string, unknown>, groupId: string): ChapterTier {\n return {\n id: String(row.id ?? \"\"),\n groupId: String(row.groupId ?? groupId),\n name: String(row.name ?? \"\"),\n priceCents: typeof row.priceCents === \"number\" ? row.priceCents : 0,\n ...(typeof row.stripePriceId === \"string\" && row.stripePriceId\n ? { stripePriceId: row.stripePriceId }\n : {}),\n ...(typeof row.blurb === \"string\" ? { blurb: row.blurb } : {}),\n sortOrder: typeof row.sortOrder === \"number\" ? row.sortOrder : 0,\n // A row that never set `active` is offered; only an explicit false retires\n // a tier, so a half-seeded row cannot silently hide a membership.\n active: row.active !== false,\n };\n}\n\n/**\n * Every tier a group offers, ordered, including the implicit tier synthesized\n * for a chapter that predates tiers. Never throws on a missing namespace: a\n * deployment whose schema has not been pushed yet reads as \"no rows\", which\n * resolves to the legacy single tier.\n */\nexport async function loadTiers(db: ChapterDb, group: TierGroupRow): Promise<ChapterTier[]> {\n const groupId = String(group.id ?? \"\");\n let rows: unknown;\n try {\n rows = (await db.query({\n tiers: { $: { where: { groupId }, order: { sortOrder: \"asc\" }, limit: 100 } },\n }) as Record<string, unknown>).tiers;\n } catch {\n rows = undefined;\n }\n const list = Array.isArray(rows)\n ? rows.map((row) => rowToTier(row as Record<string, unknown>, groupId))\n : [];\n return resolveTiers(group, list);\n}\n\n/** The tiers a join page may show: active, and joinable as configured. */\nexport async function loadOfferableTiers(\n db: ChapterDb,\n group: TierGroupRow,\n hasSecretKey: boolean,\n): Promise<ChapterTier[]> {\n return offerableTiers(await loadTiers(db, group), group, hasSecretKey);\n}\n","import type { FieldConditions } from \"@odla-ai/crm\";\nimport type { MembershipPageDocument } from \"./membership-page\";\nimport type { ChapterScheduling } from \"./types\";\nimport type { GiftOfferCatalog } from \"./gift-offers\";\n\n/** Current wire-format version for complete signup-control documents. */\nexport const SIGNUP_CONTROL_SCHEMA_VERSION = 1 as const;\n/** Package-owned follower endpoint for signed signup-control delivery. */\nexport const SIGNUP_CONTROL_PATH = \"/api/signup-control\" as const;\n\n/** One authoritative membership tier in a signup-control revision. */\nexport interface SignupControlTier {\n id: string;\n name: string;\n available: boolean;\n sortOrder: number;\n priceCents: number;\n stripePriceId?: string;\n blurb?: string;\n}\n\n/** A bounded application contract. Fields must already exist in the follower schema. */\nexport interface SignupControlApplication {\n required: readonly string[];\n optional: readonly string[];\n conditions?: Readonly<Record<string, FieldConditions>>;\n copy?: Readonly<Record<string, string>>;\n}\n\n/** Delegated legal and trust copy used by the packaged join journey. */\nexport interface SignupControlPolicy {\n disclaimerText: string;\n refundPolicyText: string;\n trustCopy?: string;\n commitmentText?: string;\n normsText?: string;\n}\n\n/** Bounded semantic design tokens delegated to the chapter signup surface. */\nexport interface SignupControlTheme {\n /** Includes color, spacing, and typography tokens such as font families. */\n tokens: Readonly<Record<string, string | number>>;\n}\n\n/** Complete desired state delivered by a controlling hub. */\nexport interface SignupControlDocument {\n schemaVersion: typeof SIGNUP_CONTROL_SCHEMA_VERSION;\n revision: number;\n generatedAt: number;\n source: { appId: string };\n target: { chapterId: string; environment: string; stripeMode: \"test\" | \"live\" };\n tiers: readonly SignupControlTier[];\n membershipPage: MembershipPageDocument;\n application?: SignupControlApplication;\n policy?: SignupControlPolicy;\n scheduling?: ChapterScheduling;\n theme?: SignupControlTheme;\n giftOffers?: GiftOfferCatalog;\n}\n\n/** Digest travels beside the document so the exact desired state is attestable. */\nexport interface SignupControlEnvelope {\n digest: string;\n document: SignupControlDocument;\n}\n\n/** Exact follower acknowledgement for one accepted or replayed revision. */\nexport interface SignupControlReceipt {\n ok: true;\n target: { chapterId: string; environment: string };\n revision: number;\n digest: string;\n status: \"accepted\" | \"replayed\";\n acknowledgedAt: number;\n}\n\n/** Stable reason codes returned when a follower refuses desired state. */\nexport type SignupControlRejection =\n | \"invalid_document\"\n | \"invalid_digest\"\n | \"wrong_source\"\n | \"wrong_target\"\n | \"wrong_environment\"\n | \"wrong_stripe_mode\"\n | \"stale_revision\"\n | \"conflicting_revision\"\n | \"materialization_failed\";\n\n/** Normalized document result returned by the package validator. */\nexport type SignupControlValidation =\n | { ok: true; value: SignupControlDocument }\n | { ok: false; errors: readonly string[] };\n","/** The first stable, shared Chapter membership-page renderer contract. */\nexport const MEMBERSHIP_PAGE_RENDERER = \"membership-cards-v1\" as const;\n\n/** Fixed visual emphasis choices supported by the versioned card renderer. */\nexport type MembershipTierVariant = \"standard\" | \"featured\" | \"supporting\";\n\n/** A bounded, token-rendered aside within one membership card. */\nexport interface MembershipTierCallout {\n label?: string;\n bodyMarkdown: string;\n}\n\n/** Scarcity copy displayed without changing tier availability or checkout. */\nexport interface MembershipTierCapacity {\n total: number;\n label?: string;\n}\n\n/**\n * Presentation attached to one server-authoritative membership tier.\n *\n * Price, free/paid state, identity, and application targeting deliberately do\n * not live here. They are resolved from the public Chapter join config so\n * authored marketing copy can never change what checkout charges.\n */\nexport interface MembershipTierPresentation {\n tierId: string;\n variant?: MembershipTierVariant;\n badge?: string;\n summaryMarkdown?: string;\n priceEyebrow?: string;\n compareAtPriceCents?: number;\n billingLabel?: string;\n priceNoteMarkdown?: string;\n capacity?: MembershipTierCapacity;\n benefits?: readonly string[];\n callout?: MembershipTierCallout;\n ctaLabel?: string;\n}\n\n/** A bounded document that can be reviewed once and rendered by any Chapter host. */\nexport interface MembershipPageDocument {\n schemaVersion: 1;\n renderer: typeof MEMBERSHIP_PAGE_RENDERER;\n tiers: readonly MembershipTierPresentation[];\n footnoteMarkdown?: string;\n}\n\n/** Minimal server-authoritative tier identity and charged amount used during validation. */\nexport interface MembershipTierAuthority {\n id: string;\n priceCents: number;\n}\n\n/** Live tier authority used to reject missing, unknown, or misleading presentation. */\nexport interface MembershipPageValidationOptions {\n /** When supplied, every live tier must occur exactly once in the document. */\n tiers?: readonly MembershipTierAuthority[];\n}\n\n/** A normalized document or the complete actionable list of validation failures. */\nexport type MembershipPageValidationResult =\n | { ok: true; value: MembershipPageDocument }\n | { ok: false; errors: readonly string[] };\n\nconst TIER_ID = /^[a-z][a-z0-9-]{0,79}$/;\nconst VARIANTS = new Set<MembershipTierVariant>([\"standard\", \"featured\", \"supporting\"]);\nconst ROOT_KEYS = new Set([\"schemaVersion\", \"renderer\", \"tiers\", \"footnoteMarkdown\"]);\nconst TIER_KEYS = new Set([\n \"tierId\", \"variant\", \"badge\", \"summaryMarkdown\", \"priceEyebrow\",\n \"compareAtPriceCents\", \"billingLabel\", \"priceNoteMarkdown\", \"capacity\",\n \"benefits\", \"callout\", \"ctaLabel\",\n]);\nconst CALLOUT_KEYS = new Set([\"label\", \"bodyMarkdown\"]);\nconst CAPACITY_KEYS = new Set([\"total\", \"label\"]);\nconst MAX_TIERS = 20;\nconst MAX_BENEFITS = 24;\nconst MAX_MARKDOWN = 65_536;\nconst MAX_LABEL = 160;\n\nconst objectRecord = (value: unknown): Record<string, unknown> | null =>\n value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null;\n\nfunction rejectUnknownKeys(\n value: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n path: string,\n errors: string[],\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) errors.push(`${path}.${key} is not supported`);\n }\n}\n\nfunction boundedString(\n value: unknown,\n path: string,\n errors: string[],\n max: number,\n required = false,\n): string | undefined {\n if (value === undefined) {\n if (required) errors.push(`${path} is required`);\n return undefined;\n }\n if (typeof value !== \"string\") {\n errors.push(`${path} must be a string`);\n return undefined;\n }\n const text = value.trim();\n if (required && !text) errors.push(`${path} is required`);\n if (text.length > max) errors.push(`${path} must be at most ${max.toLocaleString(\"en-US\")} characters`);\n return text;\n}\n\n/**\n * Validate and normalize a membership-page document without evaluating code,\n * accepting HTML, or allowing authored links/styles. Markdown slots are later\n * rendered by @odla-ai/ui's bounded safe Markdown component.\n */\nexport function validateMembershipPageDocument(\n input: unknown,\n options: MembershipPageValidationOptions = {},\n): MembershipPageValidationResult {\n const errors: string[] = [];\n const root = objectRecord(input);\n if (!root) return { ok: false, errors: [\"document must be an object\"] };\n rejectUnknownKeys(root, ROOT_KEYS, \"document\", errors);\n if (root.schemaVersion !== 1) errors.push(\"document.schemaVersion must be 1\");\n if (root.renderer !== MEMBERSHIP_PAGE_RENDERER) {\n errors.push(`document.renderer must be \\\"${MEMBERSHIP_PAGE_RENDERER}\\\"`);\n }\n if (!Array.isArray(root.tiers)) errors.push(\"document.tiers must be an array\");\n const rawTiers = Array.isArray(root.tiers) ? root.tiers : [];\n if (Array.isArray(root.tiers) && rawTiers.length === 0) errors.push(\"document.tiers must include at least one tier\");\n if (rawTiers.length > MAX_TIERS) errors.push(`document.tiers supports at most ${MAX_TIERS} entries`);\n\n const authority = new Map((options.tiers ?? []).map((tier) => [tier.id, tier]));\n const seen = new Set<string>();\n const tiers: MembershipTierPresentation[] = [];\n for (const [index, raw] of rawTiers.slice(0, MAX_TIERS).entries()) {\n const path = `document.tiers[${index}]`;\n const item = objectRecord(raw);\n if (!item) {\n errors.push(`${path} must be an object`);\n continue;\n }\n rejectUnknownKeys(item, TIER_KEYS, path, errors);\n const tierId = boundedString(item.tierId, `${path}.tierId`, errors, 80, true) ?? \"\";\n if (tierId && !TIER_ID.test(tierId)) errors.push(`${path}.tierId must be a lowercase kebab-case id`);\n if (seen.has(tierId)) errors.push(`${path}.tierId duplicates \\\"${tierId}\\\"`);\n seen.add(tierId);\n if (authority.size && !authority.has(tierId)) errors.push(`${path}.tierId \\\"${tierId}\\\" is not an offered tier`);\n\n const variant = item.variant;\n if (variant !== undefined && (typeof variant !== \"string\" || !VARIANTS.has(variant as MembershipTierVariant))) {\n errors.push(`${path}.variant must be standard, featured, or supporting`);\n }\n const compareAt = item.compareAtPriceCents;\n if (compareAt !== undefined && (!Number.isInteger(compareAt) || Number(compareAt) < 0 || Number(compareAt) > 100_000_000)) {\n errors.push(`${path}.compareAtPriceCents must be an integer from 0 to 100,000,000`);\n }\n const actual = authority.get(tierId)?.priceCents;\n if (Number.isInteger(compareAt) && actual !== undefined && Number(compareAt) <= actual) {\n errors.push(`${path}.compareAtPriceCents must be greater than the authoritative tier price`);\n }\n\n let benefits: string[] | undefined;\n if (item.benefits !== undefined) {\n if (!Array.isArray(item.benefits)) errors.push(`${path}.benefits must be an array`);\n else {\n if (item.benefits.length > MAX_BENEFITS) errors.push(`${path}.benefits supports at most ${MAX_BENEFITS} entries`);\n benefits = item.benefits.slice(0, MAX_BENEFITS).flatMap((benefit, benefitIndex) => {\n const text = boundedString(benefit, `${path}.benefits[${benefitIndex}]`, errors, 2_000, true);\n return text ? [text] : [];\n });\n }\n }\n\n let callout: MembershipTierCallout | undefined;\n if (item.callout !== undefined) {\n const rawCallout = objectRecord(item.callout);\n if (!rawCallout) errors.push(`${path}.callout must be an object`);\n else {\n rejectUnknownKeys(rawCallout, CALLOUT_KEYS, `${path}.callout`, errors);\n const bodyMarkdown = boundedString(rawCallout.bodyMarkdown, `${path}.callout.bodyMarkdown`, errors, MAX_MARKDOWN, true);\n const label = boundedString(rawCallout.label, `${path}.callout.label`, errors, MAX_LABEL);\n if (bodyMarkdown) callout = { ...(label ? { label } : {}), bodyMarkdown };\n }\n }\n\n let capacity: MembershipTierCapacity | undefined;\n if (item.capacity !== undefined) {\n const rawCapacity = objectRecord(item.capacity);\n if (!rawCapacity) errors.push(`${path}.capacity must be an object`);\n else {\n rejectUnknownKeys(rawCapacity, CAPACITY_KEYS, `${path}.capacity`, errors);\n const total = rawCapacity.total;\n if (!Number.isInteger(total) || Number(total) < 1 || Number(total) > 1_000_000) {\n errors.push(`${path}.capacity.total must be an integer from 1 to 1,000,000`);\n }\n const label = boundedString(rawCapacity.label, `${path}.capacity.label`, errors, MAX_LABEL);\n if (Number.isInteger(total) && Number(total) >= 1 && Number(total) <= 1_000_000) {\n capacity = { total: Number(total), ...(label ? { label } : {}) };\n }\n }\n }\n\n const badge = boundedString(item.badge, `${path}.badge`, errors, MAX_LABEL);\n const summaryMarkdown = boundedString(item.summaryMarkdown, `${path}.summaryMarkdown`, errors, MAX_MARKDOWN);\n const priceEyebrow = boundedString(item.priceEyebrow, `${path}.priceEyebrow`, errors, MAX_LABEL);\n const billingLabel = boundedString(item.billingLabel, `${path}.billingLabel`, errors, MAX_LABEL);\n const priceNoteMarkdown = boundedString(item.priceNoteMarkdown, `${path}.priceNoteMarkdown`, errors, MAX_MARKDOWN);\n const ctaLabel = boundedString(item.ctaLabel, `${path}.ctaLabel`, errors, MAX_LABEL);\n tiers.push({\n tierId,\n ...(typeof variant === \"string\" && VARIANTS.has(variant as MembershipTierVariant) ? { variant: variant as MembershipTierVariant } : {}),\n ...(badge ? { badge } : {}),\n ...(summaryMarkdown ? { summaryMarkdown } : {}),\n ...(priceEyebrow ? { priceEyebrow } : {}),\n ...(Number.isInteger(compareAt) ? { compareAtPriceCents: Number(compareAt) } : {}),\n ...(billingLabel ? { billingLabel } : {}),\n ...(priceNoteMarkdown ? { priceNoteMarkdown } : {}),\n ...(capacity ? { capacity } : {}),\n ...(benefits ? { benefits } : {}),\n ...(callout ? { callout } : {}),\n ...(ctaLabel ? { ctaLabel } : {}),\n });\n }\n if (authority.size) {\n for (const tierId of authority.keys()) {\n if (!seen.has(tierId)) errors.push(`document.tiers is missing offered tier \\\"${tierId}\\\"`);\n }\n }\n const footnoteMarkdown = boundedString(root.footnoteMarkdown, \"document.footnoteMarkdown\", errors, MAX_MARKDOWN);\n if (errors.length) return { ok: false, errors };\n return {\n ok: true,\n value: {\n schemaVersion: 1,\n renderer: MEMBERSHIP_PAGE_RENDERER,\n tiers,\n ...(footnoteMarkdown ? { footnoteMarkdown } : {}),\n },\n };\n}\n\n/** Validate a document or fail closed with all actionable validation errors. */\nexport function membershipPageDocument(\n input: unknown,\n options: MembershipPageValidationOptions = {},\n): MembershipPageDocument {\n const result = validateMembershipPageDocument(input, options);\n if (!result.ok) throw new TypeError(`Invalid membership page document: ${result.errors.join(\"; \")}`);\n return result.value;\n}\n","import { resolveApplication } from \"./member\";\nimport { validateMembershipPageDocument } from \"./membership-page\";\nimport { validateScheduling } from \"./scheduling\";\nimport { validateGiftOfferCatalog } from \"./gift-offers\";\nimport type {\n SignupControlApplication,\n SignupControlDocument,\n SignupControlPolicy,\n SignupControlTheme,\n SignupControlTier,\n SignupControlValidation,\n} from \"./signup-control-contract\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst ENVIRONMENT = /^[a-z][a-z0-9_-]{0,62}$/;\nconst TIER = /^[a-z][a-z0-9-]{0,79}$/;\nconst PRICE = /^price_[A-Za-z0-9]{12,}$/;\nconst ROOT_KEYS = new Set([\n \"schemaVersion\", \"revision\", \"generatedAt\", \"source\", \"target\", \"tiers\",\n \"membershipPage\", \"application\", \"policy\", \"scheduling\", \"theme\", \"giftOffers\",\n]);\nconst TIER_KEYS = new Set([\"id\", \"name\", \"available\", \"sortOrder\", \"priceCents\", \"stripePriceId\", \"blurb\"]);\n\nconst recordOf = (value: unknown): Record<string, unknown> | null =>\n value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null;\n\nfunction unknownKeys(value: Record<string, unknown>, allowed: ReadonlySet<string>, path: string, errors: string[]): void {\n for (const key of Object.keys(value)) if (!allowed.has(key)) errors.push(`${path}.${key} is not supported`);\n}\n\nfunction text(value: unknown, path: string, errors: string[], max = 65_536): string {\n if (typeof value !== \"string\" || !value.trim()) {\n errors.push(`${path} is required`);\n return \"\";\n }\n if (value.length > max) errors.push(`${path} must be at most ${max} characters`);\n return value.trim();\n}\n\nfunction tiersOf(value: unknown, errors: string[]): SignupControlTier[] {\n if (!Array.isArray(value) || !value.length) {\n errors.push(\"document.tiers must be a non-empty array\");\n return [];\n }\n if (value.length > 20) errors.push(\"document.tiers supports at most 20 entries\");\n const seen = new Set<string>();\n return value.slice(0, 20).flatMap((raw, index) => {\n const path = `document.tiers[${index}]`;\n const item = recordOf(raw);\n if (!item) {\n errors.push(`${path} must be an object`);\n return [];\n }\n unknownKeys(item, TIER_KEYS, path, errors);\n const id = text(item.id, `${path}.id`, errors, 80);\n if (id && !TIER.test(id)) errors.push(`${path}.id must be a lowercase kebab-case id`);\n if (seen.has(id)) errors.push(`${path}.id duplicates \"${id}\"`);\n seen.add(id);\n const name = text(item.name, `${path}.name`, errors, 160);\n if (typeof item.available !== \"boolean\") errors.push(`${path}.available must be boolean`);\n if (!Number.isInteger(item.sortOrder) || Number(item.sortOrder) < 0) errors.push(`${path}.sortOrder must be a non-negative integer`);\n if (!Number.isInteger(item.priceCents) || Number(item.priceCents) < 0 || Number(item.priceCents) > 100_000_000) {\n errors.push(`${path}.priceCents must be an integer from 0 to 100,000,000`);\n }\n if (item.stripePriceId !== undefined && (typeof item.stripePriceId !== \"string\" || !PRICE.test(item.stripePriceId))) {\n errors.push(`${path}.stripePriceId must be a real Stripe Price id`);\n }\n if (item.available === true && Number(item.priceCents) > 0 && !item.stripePriceId) {\n errors.push(`${path}.stripePriceId is required for an available paid tier`);\n }\n const blurb = item.blurb === undefined ? undefined : text(item.blurb, `${path}.blurb`, errors, 4_000);\n return [{\n id, name, available: item.available === true,\n sortOrder: Number(item.sortOrder) || 0,\n priceCents: Number(item.priceCents) || 0,\n ...(typeof item.stripePriceId === \"string\" ? { stripePriceId: item.stripePriceId } : {}),\n ...(blurb ? { blurb } : {}),\n }];\n });\n}\n\nfunction applicationOf(value: unknown, errors: string[]): SignupControlApplication | undefined {\n if (value === undefined) return undefined;\n const input = recordOf(value);\n if (!input) {\n errors.push(\"document.application must be an object\");\n return undefined;\n }\n unknownKeys(input, new Set([\"required\", \"optional\", \"conditions\", \"copy\"]), \"document.application\", errors);\n try {\n const resolved = resolveApplication(input);\n const copy = recordOf(input.copy);\n if (input.copy !== undefined && (!copy || Object.values(copy).some((item) => typeof item !== \"string\"))) {\n errors.push(\"document.application.copy must contain only string values\");\n }\n return {\n required: resolved.required,\n optional: resolved.optional,\n ...(Object.keys(resolved.conditions).length ? { conditions: resolved.conditions } : {}),\n ...(copy ? { copy: copy as Record<string, string> } : {}),\n };\n } catch (error) {\n errors.push(error instanceof Error ? error.message : \"document.application is invalid\");\n return undefined;\n }\n}\n\nfunction policyOf(value: unknown, errors: string[]): SignupControlPolicy | undefined {\n if (value === undefined) return undefined;\n const input = recordOf(value);\n if (!input) {\n errors.push(\"document.policy must be an object\");\n return undefined;\n }\n const allowed = new Set([\"disclaimerText\", \"refundPolicyText\", \"trustCopy\", \"commitmentText\", \"normsText\"]);\n unknownKeys(input, allowed, \"document.policy\", errors);\n const result = {} as Record<string, string>;\n for (const key of allowed) {\n if (input[key] === undefined && key !== \"disclaimerText\" && key !== \"refundPolicyText\") continue;\n result[key] = text(input[key], `document.policy.${key}`, errors);\n }\n return result as unknown as SignupControlPolicy;\n}\n\nfunction themeOf(value: unknown, errors: string[]): SignupControlTheme | undefined {\n if (value === undefined) return undefined;\n const input = recordOf(value);\n const tokens = recordOf(input?.tokens);\n if (!input || !tokens) {\n errors.push(\"document.theme.tokens must be an object\");\n return undefined;\n }\n unknownKeys(input, new Set([\"tokens\"]), \"document.theme\", errors);\n if (Object.keys(tokens).length > 256) errors.push(\"document.theme.tokens supports at most 256 entries\");\n let serializedLength = 0;\n for (const [key, token] of Object.entries(tokens)) {\n if (!/^--ui-[a-z0-9][a-z0-9-]{0,94}$/.test(key)) {\n errors.push(`document.theme.tokens.${key} must be an allowlisted --ui-* custom property`);\n }\n const rendered = String(token).trim();\n serializedLength += key.length + rendered.length + 4;\n if ((typeof token !== \"string\" && typeof token !== \"number\") ||\n (typeof token === \"number\" && !Number.isFinite(token)) ||\n !rendered || rendered.length > 1_000 ||\n /[\\u0000-\\u001f\\u007f\\\\<>{};]|\\/\\*|\\*\\/|(?:^|[^a-z])(?:url|expression)\\s*\\(|@import/i.test(rendered)) {\n errors.push(`document.theme.tokens.${key} must be a bounded breakout-safe CSS value`);\n }\n }\n if (serializedLength > 65_536) errors.push(\"document.theme.tokens exceeds the serialized size bound\");\n return { tokens: tokens as Record<string, string | number> };\n}\n\n/** Validate and normalize one complete desired signup state. */\nexport function validateSignupControlDocument(input: unknown): SignupControlValidation {\n const errors: string[] = [];\n const root = recordOf(input);\n if (!root) return { ok: false, errors: [\"document must be an object\"] };\n unknownKeys(root, ROOT_KEYS, \"document\", errors);\n if (root.schemaVersion !== 1) errors.push(\"document.schemaVersion must be 1\");\n if (!Number.isSafeInteger(root.revision) || Number(root.revision) < 1) errors.push(\"document.revision must be a positive integer\");\n if (!Number.isSafeInteger(root.generatedAt) || Number(root.generatedAt) < 1) errors.push(\"document.generatedAt must be epoch milliseconds\");\n const source = recordOf(root.source);\n const target = recordOf(root.target);\n const appId = text(source?.appId, \"document.source.appId\", errors, 63);\n const chapterId = text(target?.chapterId, \"document.target.chapterId\", errors, 63);\n const environment = text(target?.environment, \"document.target.environment\", errors, 63);\n if (appId && !SLUG.test(appId)) errors.push(\"document.source.appId must be a lowercase app slug\");\n if (chapterId && !SLUG.test(chapterId)) errors.push(\"document.target.chapterId must be a lowercase app slug\");\n if (environment && !ENVIRONMENT.test(environment)) errors.push(\"document.target.environment is invalid\");\n if (target?.stripeMode !== \"test\" && target?.stripeMode !== \"live\") errors.push(\"document.target.stripeMode must be test or live\");\n const tiers = tiersOf(root.tiers, errors);\n const available = tiers.filter((tier) => tier.available).sort((a, b) => a.sortOrder - b.sortOrder);\n const page = validateMembershipPageDocument(root.membershipPage, { tiers: available });\n if (!page.ok) errors.push(...page.errors);\n else if (page.value.tiers.some((tier, index) => tier.tierId !== available[index]?.id)) {\n errors.push(\"document.membershipPage.tiers must follow the available tier display order\");\n }\n const application = applicationOf(root.application, errors);\n const policy = policyOf(root.policy, errors);\n let scheduling;\n if (root.scheduling !== undefined) {\n const checked = validateScheduling(root.scheduling as never);\n if (!checked.ok) errors.push(...Object.entries(checked.errors).map(([key, value]) => `document.scheduling.${key}: ${value}`));\n else scheduling = root.scheduling;\n }\n const theme = themeOf(root.theme, errors);\n const giftOffers = root.giftOffers === undefined\n ? undefined\n : validateGiftOfferCatalog(root.giftOffers, new Set(tiers.map((tier) => tier.id)));\n if (giftOffers && !giftOffers.ok) errors.push(...giftOffers.errors);\n if (errors.length || !page.ok) return { ok: false, errors };\n return { ok: true, value: {\n schemaVersion: 1,\n revision: Number(root.revision),\n generatedAt: Number(root.generatedAt),\n source: { appId },\n target: { chapterId, environment, stripeMode: target?.stripeMode as \"test\" | \"live\" },\n tiers,\n membershipPage: page.value,\n ...(application ? { application } : {}),\n ...(policy ? { policy } : {}),\n ...(scheduling ? { scheduling } : {}),\n ...(theme ? { theme } : {}),\n ...(giftOffers?.ok ? { giftOffers: giftOffers.value } : {}),\n } };\n}\n","import type { SignupControlTheme } from \"./signup-control-contract\";\n\n/** Stable marker a static document can place where managed signup tokens belong. */\nexport const SIGNUP_CONTROL_THEME_MARKER = \"<!--odla:signup-control-theme-->\" as const;\n/** Stable id shared by the server renderer and browser hydration helper. */\nexport const SIGNUP_CONTROL_THEME_STYLE_ID = \"odla-signup-control-theme\" as const;\n\nconst TOKEN_NAME = /^--ui-[a-z0-9][a-z0-9-]{0,94}$/;\nconst DIGEST = /^sha256:[0-9a-f]{64}$/;\nconst UNSAFE_VALUE = /[\\u0000-\\u001f\\u007f\\\\<>{};]|\\/\\*|\\*\\/|(?:^|[^a-z])(?:url|expression)\\s*\\(|@import/i;\nconst MAX_TOKENS = 256;\nconst MAX_VALUE_LENGTH = 1_000;\nconst MAX_SERIALIZED_LENGTH = 65_536;\n\n/** The active revision shape exposed by `GET /api/join-config`. */\nexport interface SignupControlThemeRevision {\n revision: number;\n digest: string;\n theme?: SignupControlTheme;\n}\n\n/** Identity shared by initial HTML, response caching, and client hydration. */\nexport interface SignupControlThemeMetadata {\n source: \"active\" | \"bootstrap\";\n revision: number | null;\n digest: string | null;\n /** Include this value in any host-owned cache key for transformed HTML. */\n cacheKey: string;\n}\n\n/** A validated style block ready to place in an HTML head. */\nexport interface SignupControlThemeHead {\n css: string;\n head: string;\n metadata: SignupControlThemeMetadata;\n}\n\n/** Minimal DOM surface required by {@link hydrateSignupControlTheme}. */\nexport interface SignupControlThemeStyleTarget {\n textContent: string | null;\n getAttribute(name: string): string | null;\n setAttribute(name: string, value: string): void;\n removeAttribute(name: string): void;\n}\n\n/** Host-owned fallback inputs shared by server rendering and hydration. */\nexport interface SignupControlThemeOptions {\n /** Local site-owned tokens used only when no active managed revision exists. */\n bootstrapTokens?: Readonly<Record<string, string | number>>;\n}\n\nfunction validatedTokens(\n input: Readonly<Record<string, string | number>> | undefined,\n): Readonly<Record<string, string>> {\n const entries = Object.entries(input ?? {});\n if (entries.length > MAX_TOKENS) {\n throw new TypeError(`signup-control theme supports at most ${MAX_TOKENS} tokens`);\n }\n const tokens: Record<string, string> = {};\n let serializedLength = 0;\n for (const [name, raw] of entries.sort(([left], [right]) => left.localeCompare(right))) {\n if (!TOKEN_NAME.test(name)) {\n throw new TypeError(`signup-control theme token \"${name}\" must be an allowlisted --ui-* property`);\n }\n if ((typeof raw !== \"string\" && typeof raw !== \"number\") ||\n (typeof raw === \"number\" && !Number.isFinite(raw))) {\n throw new TypeError(`signup-control theme token \"${name}\" must be a finite string or number`);\n }\n const value = String(raw).trim();\n if (!value || value.length > MAX_VALUE_LENGTH || UNSAFE_VALUE.test(value)) {\n throw new TypeError(`signup-control theme token \"${name}\" has an unsafe or oversized value`);\n }\n serializedLength += name.length + value.length + 4;\n if (serializedLength > MAX_SERIALIZED_LENGTH) {\n throw new TypeError(\"signup-control theme exceeds the serialized size bound\");\n }\n tokens[name] = value;\n }\n return tokens;\n}\n\nfunction cssFor(tokens: Readonly<Record<string, string>>): string {\n const declarations = Object.entries(tokens).map(([name, value]) => ` ${name}: ${value};`);\n return declarations.length ? `:root {\\n${declarations.join(\"\\n\")}\\n}` : \"\";\n}\n\nfunction stateFor(\n revision: SignupControlThemeRevision | null,\n options: SignupControlThemeOptions,\n): { css: string; metadata: SignupControlThemeMetadata } {\n if (!revision) {\n return {\n css: cssFor(validatedTokens(options.bootstrapTokens)),\n metadata: { source: \"bootstrap\", revision: null, digest: null, cacheKey: \"signup-control:bootstrap\" },\n };\n }\n if (!Number.isSafeInteger(revision.revision) || revision.revision < 1 || !DIGEST.test(revision.digest)) {\n throw new TypeError(\"signup-control theme revision metadata is invalid\");\n }\n return {\n css: cssFor(validatedTokens(revision.theme?.tokens)),\n metadata: {\n source: \"active\",\n revision: revision.revision,\n digest: revision.digest,\n cacheKey: `signup-control:${revision.digest}`,\n },\n };\n}\n\nfunction attributes(metadata: SignupControlThemeMetadata): string {\n return [\n `id=\"${SIGNUP_CONTROL_THEME_STYLE_ID}\"`,\n `data-signup-control-source=\"${metadata.source}\"`,\n `data-signup-control-cache-key=\"${metadata.cacheKey}\"`,\n ...(metadata.revision === null ? [] : [`data-signup-control-revision=\"${metadata.revision}\"`]),\n ...(metadata.digest === null ? [] : [`data-signup-control-digest=\"${metadata.digest}\"`]),\n ].join(\" \");\n}\n\n/**\n * Render validated signup-control tokens for the initial HTML head. Passing\n * `null` emits the deterministic local bootstrap state; it never performs I/O.\n */\nexport function renderSignupControlThemeHead(\n revision: SignupControlThemeRevision | null,\n options: SignupControlThemeOptions = {},\n): SignupControlThemeHead {\n const { css, metadata } = stateFor(revision, options);\n return { css, metadata, head: `<style ${attributes(metadata)}>${css}</style>` };\n}\n\n/**\n * Replace the stable marker (preferred), an earlier Chapter style block, or the\n * closing head tag. The returned HTML always contains exactly one managed block.\n */\nexport function injectSignupControlThemeHead(\n html: string,\n rendered: SignupControlThemeHead,\n marker: string = SIGNUP_CONTROL_THEME_MARKER,\n): string {\n const existing = /<style\\b(?=[^>]*\\bid\\s*=\\s*[\"']odla-signup-control-theme[\"'])[^>]*>[\\s\\S]*?<\\/style>/gi;\n const existingBlocks = html.match(existing) ?? [];\n if (existingBlocks.length > 1) {\n throw new TypeError(\"signup-control theme style block must appear at most once\");\n }\n if (existingBlocks.length === 1) return html.replace(existing, rendered.head);\n const markerIndex = html.indexOf(marker);\n if (markerIndex >= 0) {\n if (html.indexOf(marker, markerIndex + marker.length) >= 0) {\n throw new TypeError(\"signup-control theme marker must appear exactly once\");\n }\n return `${html.slice(0, markerIndex)}${rendered.head}${html.slice(markerIndex + marker.length)}`;\n }\n const closingHead = html.search(/<\\/head\\s*>/i);\n if (closingHead < 0) throw new TypeError(\"signup-control theme requires an HTML head\");\n return `${html.slice(0, closingHead)}${rendered.head}${html.slice(closingHead)}`;\n}\n\n/**\n * Apply a newly fetched revision to the server-rendered style element. When the\n * revision and digest already match, this performs no writes and returns false,\n * so hydration cannot cause a visual token change.\n */\nexport function hydrateSignupControlTheme(\n target: SignupControlThemeStyleTarget,\n revision: SignupControlThemeRevision | null,\n options: SignupControlThemeOptions = {},\n): boolean {\n const next = stateFor(revision, options);\n const currentSource = target.getAttribute(\"data-signup-control-source\");\n const currentRevision = target.getAttribute(\"data-signup-control-revision\");\n const currentDigest = target.getAttribute(\"data-signup-control-digest\");\n if (currentSource === next.metadata.source &&\n currentRevision === (next.metadata.revision === null ? null : String(next.metadata.revision)) &&\n currentDigest === next.metadata.digest) {\n return false;\n }\n target.textContent = next.css;\n target.setAttribute(\"data-signup-control-source\", next.metadata.source);\n target.setAttribute(\"data-signup-control-cache-key\", next.metadata.cacheKey);\n if (next.metadata.revision === null) target.removeAttribute(\"data-signup-control-revision\");\n else target.setAttribute(\"data-signup-control-revision\", String(next.metadata.revision));\n if (next.metadata.digest === null) target.removeAttribute(\"data-signup-control-digest\");\n else target.setAttribute(\"data-signup-control-digest\", next.metadata.digest);\n return true;\n}\n","import type { MembershipTierPresentation } from \"./membership-page\";\n\n/** A presentation overlay parsed from the constrained membership Markdown convention. */\nexport type MembershipTierMarkdownResult =\n | { ok: true; value: MembershipTierPresentation }\n | { ok: false; errors: readonly string[] };\n\nconst MAX_BENEFITS = 24;\nconst MAX_MARKDOWN = 65_536;\nconst MAX_LABEL = 160;\nconst MARKDOWN_SECTION = /^##\\s+(.+?)\\s*$/;\nconst MARKDOWN_HEADING = /^#{1,6}\\s+/;\nconst MARKDOWN_BENEFIT = /^\\s*[-*+]\\s+(.+?)\\s*$/;\n\ntype MembershipMarkdownSection = \"summary\" | \"benefits\" | \"priceNote\" | \"callout\" | \"action\";\n\nfunction markdownSection(rawHeading: string): { section?: MembershipMarkdownSection; calloutLabel?: string } {\n const heading = rawHeading.trim();\n const normalized = heading.toLowerCase();\n if (normalized === \"summary\") return { section: \"summary\" };\n if (normalized === \"benefits\") return { section: \"benefits\" };\n if (normalized === \"price note\" || normalized === \"rate note\") return { section: \"priceNote\" };\n if (normalized === \"action\" || normalized === \"call to action\") return { section: \"action\" };\n const callout = heading.match(/^callout(?:\\s*[:—-]\\s*(.+))?$/i);\n if (callout) return { section: \"callout\", ...(callout[1]?.trim() ? { calloutLabel: callout[1].trim() } : {}) };\n return {};\n}\n\nfunction markdownBenefits(lines: readonly string[], path: string, errors: string[]): string[] {\n const benefits: string[] = [];\n for (const [index, line] of lines.entries()) {\n if (!line.trim()) continue;\n const match = line.match(MARKDOWN_BENEFIT);\n if (!match) {\n errors.push(`${path} line ${index + 1} must be a Markdown bullet`);\n continue;\n }\n const text = (match[1] ?? \"\").trim();\n if (text.length > 2_000) errors.push(`${path} line ${index + 1} must be at most 2,000 characters`);\n if (text) benefits.push(text);\n }\n if (benefits.length > MAX_BENEFITS) errors.push(`${path} supports at most ${MAX_BENEFITS} entries`);\n return benefits.slice(0, MAX_BENEFITS);\n}\n\n/**\n * Apply authored Markdown to the text slots of an existing tier presentation.\n *\n * The convention is deliberately small and reviewable:\n * - prelude prose -> summary; prelude bullets -> benefits\n * - `## Summary`, `## Benefits`, `## Price note`, `## Callout: Label`,\n * and `## Action` target those exact renderer slots\n *\n * Identity, price, scarcity, variants, badges, links, HTML, and CSS remain in\n * the reviewed presentation/authority contract and cannot be authored here.\n */\nexport function applyMembershipTierMarkdown(\n presentation: MembershipTierPresentation,\n source: string,\n): MembershipTierMarkdownResult {\n if (typeof source !== \"string\") return { ok: false, errors: [\"membership Markdown must be a string\"] };\n if (source.length > MAX_MARKDOWN) {\n return { ok: false, errors: [`membership Markdown must be at most ${MAX_MARKDOWN.toLocaleString(\"en-US\")} characters`] };\n }\n if (!source.trim()) return { ok: true, value: { ...presentation } };\n\n const errors: string[] = [];\n const sections = new Map<MembershipMarkdownSection, { lines: string[]; calloutLabel?: string }>();\n const prelude: string[] = [];\n let current: MembershipMarkdownSection | null = null;\n for (const [index, line] of source.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\").entries()) {\n const heading = line.match(MARKDOWN_SECTION);\n if (heading) {\n const headingText = heading[1] ?? \"\";\n const parsed = markdownSection(headingText);\n if (!parsed.section) {\n errors.push(`membership Markdown heading \"${headingText.trim()}\" is not supported`);\n current = null;\n continue;\n }\n if (sections.has(parsed.section)) {\n errors.push(`membership Markdown repeats the ${parsed.section} section`);\n current = parsed.section;\n continue;\n }\n sections.set(parsed.section, { lines: [], ...(parsed.calloutLabel ? { calloutLabel: parsed.calloutLabel } : {}) });\n current = parsed.section;\n continue;\n }\n if (MARKDOWN_HEADING.test(line)) {\n errors.push(`membership Markdown line ${index + 1} uses an unsupported heading`);\n continue;\n }\n if (current) sections.get(current)?.lines.push(line);\n else prelude.push(line);\n }\n\n const preludeBenefits: string[] = [];\n const preludeSummary: string[] = [];\n for (const line of prelude) {\n const benefit = line.match(MARKDOWN_BENEFIT);\n if (benefit) preludeBenefits.push((benefit[1] ?? \"\").trim());\n else preludeSummary.push(line);\n }\n if (preludeBenefits.length > MAX_BENEFITS) errors.push(`membership Markdown prelude supports at most ${MAX_BENEFITS} benefits`);\n if (preludeBenefits.some((benefit) => benefit.length > 2_000)) errors.push(\"membership Markdown benefits must be at most 2,000 characters\");\n\n const summarySection = sections.get(\"summary\");\n const benefitsSection = sections.get(\"benefits\");\n const priceNoteSection = sections.get(\"priceNote\");\n const calloutSection = sections.get(\"callout\");\n const actionSection = sections.get(\"action\");\n const summaryMarkdown = (summarySection?.lines ?? preludeSummary).join(\"\\n\").trim();\n const benefits = benefitsSection\n ? markdownBenefits(benefitsSection.lines, \"membership Markdown Benefits\", errors)\n : preludeBenefits.filter(Boolean).slice(0, MAX_BENEFITS);\n const priceNoteMarkdown = priceNoteSection?.lines.join(\"\\n\").trim();\n const calloutBody = calloutSection?.lines.join(\"\\n\").trim();\n const actionLines = actionSection?.lines.filter((line) => line.trim());\n const ctaLabel = actionLines?.join(\" \").trim();\n if (actionLines && actionLines.length !== 1) errors.push(\"membership Markdown Action must contain exactly one line\");\n if (ctaLabel && ctaLabel.length > MAX_LABEL) errors.push(`membership Markdown Action must be at most ${MAX_LABEL} characters`);\n if (calloutSection && !calloutBody) errors.push(\"membership Markdown Callout must include body copy\");\n if (calloutSection?.calloutLabel && calloutSection.calloutLabel.length > MAX_LABEL) {\n errors.push(`membership Markdown Callout label must be at most ${MAX_LABEL} characters`);\n }\n if (errors.length) return { ok: false, errors };\n\n return {\n ok: true,\n value: {\n ...presentation,\n ...(summaryMarkdown ? { summaryMarkdown } : {}),\n ...(benefitsSection || preludeBenefits.length ? { benefits } : {}),\n ...(priceNoteSection ? { priceNoteMarkdown: priceNoteMarkdown ?? \"\" } : {}),\n ...(calloutSection ? {\n callout: {\n ...(calloutSection.calloutLabel || presentation.callout?.label\n ? { label: calloutSection.calloutLabel ?? presentation.callout?.label }\n : {}),\n bodyMarkdown: calloutBody ?? \"\",\n },\n } : {}),\n ...(actionSection && ctaLabel ? { ctaLabel } : {}),\n },\n };\n}\n\n/** Apply constrained membership Markdown or fail closed with actionable errors. */\nexport function membershipTierPresentationFromMarkdown(\n presentation: MembershipTierPresentation,\n source: string,\n): MembershipTierPresentation {\n const result = applyMembershipTierMarkdown(presentation, source);\n if (!result.ok) throw new TypeError(`Invalid membership Markdown: ${result.errors.join(\"; \")}`);\n return result.value;\n}\n","import {\n canonicalPromotionValue,\n type PromotionAdapterResult,\n type PromotionArtifactInput,\n type PromotionExclusion,\n} from \"@odla-ai/promotion\";\nimport { signupControlDigest } from \"./signup-control-canonical\";\nimport type { SignupControlDocument } from \"./signup-control-contract\";\nimport { validateSignupControlDocument } from \"./signup-control-validate\";\n\n/** Stable adapter identity bound into Chapter artifact provenance. */\nexport const CHAPTER_PROMOTION_ADAPTER = \"@odla-ai/chapter/v1\";\n\n/** One exact, digest-verified signup-control revision to export. */\nexport interface ChapterPromotionInput {\n document: SignupControlDocument;\n digest: string;\n}\n\nconst exclusions = (chapterId: string, paidTierIds: string[]): PromotionExclusion[] => [\n {\n kind: \"chapter.providers\", id: chapterId, reason: \"provider_identity\",\n paths: [\n ...paidTierIds.map((id) => `tiers[${id}].stripePriceId`),\n \"groups.stripePublishableKey\", \"applications.stripeCustomerId\",\n \"applications.stripeSubscriptionId\", \"meetings.googleEventId\",\n ],\n detail: \"Stripe, Clerk, and Google identities are resolved independently in each target environment.\",\n },\n {\n kind: \"chapter.runtime\", id: chapterId, reason: \"runtime_state\",\n paths: [\"applications.*\", \"meetings.*\", \"emailLog.*\", \"crm_*.*\"],\n detail: \"Applicants, meetings, messages, and CRM rows are operational state, not managed signup content.\",\n },\n {\n kind: \"chapter.access\", id: chapterId, reason: \"personal_data\",\n paths: [\"admins.*\", \"superAdmins.*\", \"networkNotes.*\"],\n detail: \"People, access lists, and private network notes remain local to the target environment.\",\n },\n {\n kind: \"chapter.history\", id: chapterId, reason: \"authority_history\",\n paths: [\"signupControls[active=false]\", \"signupControls.*At\", \"signupControls.environment\"],\n detail: \"The source retains immutable delivery history; only selected published content is exported.\",\n },\n];\n\n/** Export the provider-independent pieces of one exact active signup revision. */\nexport async function exportChapterPromotion(input: ChapterPromotionInput): Promise<PromotionAdapterResult> {\n if (!/^sha256:[0-9a-f]{64}$/.test(input.digest)) throw new TypeError(\"chapter promotion digest is invalid\");\n const checked = validateSignupControlDocument(input.document);\n if (!checked.ok) throw new TypeError(checked.errors.join(\"; \"));\n const document = checked.value;\n if (await signupControlDigest(document) !== input.digest) throw new TypeError(\"chapter promotion digest does not match its document\");\n const revision = `chapter:${document.target.chapterId}:${document.revision}`;\n const promotionProvenance = {\n adapter: CHAPTER_PROMOTION_ADAPTER,\n sourceIds: [`signup-control:${document.revision}`, document.source.appId, document.target.chapterId].sort(),\n receiptDigests: [input.digest as `sha256:${string}`],\n };\n const artifact = (kind: string, id: string, content: unknown): PromotionArtifactInput => ({\n kind, id, sourceRevision: revision, provenance: promotionProvenance,\n content: canonicalPromotionValue(content),\n });\n const chapterId = document.target.chapterId;\n const artifacts = [\n artifact(\"chapter.catalog\", chapterId, {\n chapterId,\n tiers: document.tiers.map(({ stripePriceId: _providerId, ...tier }) => tier),\n }),\n artifact(\"chapter.membership-page\", chapterId, document.membershipPage),\n ...(document.application ? [artifact(\"chapter.application\", chapterId, document.application)] : []),\n ...(document.policy ? [artifact(\"chapter.policy\", chapterId, document.policy)] : []),\n ...(document.scheduling ? [artifact(\"chapter.scheduling\", chapterId, document.scheduling)] : []),\n ...(document.theme ? [artifact(\"chapter.theme\", chapterId, document.theme)] : []),\n ];\n return {\n adapter: CHAPTER_PROMOTION_ADAPTER,\n artifacts,\n exclusions: exclusions(chapterId, document.tiers.filter((tier) => tier.stripePriceId).map((tier) => tier.id)),\n preconditions: [\n {\n code: \"chapter.signup-control.schema\", path: \"services.chapter.signupControl.schemaVersion\", expected: document.schemaVersion,\n detail: \"The target must support this Chapter signup-control document version.\",\n },\n {\n code: \"chapter.identity\", path: \"app.appId\", expected: chapterId,\n detail: \"Chapter content can only target the chapter named by the signed source revision.\",\n },\n ],\n };\n}\n"],"mappings":";AAEA,SAAS,iBAAiB;;;ACI1B,SAAS,sBAAsB,0BAA0B;;;ACDzD,IAAM,wBAAwB;AAQ9B,eAAsB,2BAA2B,cAAuC;AACtF,QAAM,QAAQ,IAAI,YAAY,EAAE,OAAO,GAAG,qBAAqB,GAAG,YAAY,EAAE;AAChF,QAAM,QAAQ,IAAI,WAAW,MAAM,OAAO,OAAO,OAAO,WAAW,KAAK,CAAC,EAAE,MAAM,GAAG,EAAE;AACtF,QAAM,CAAC,IAAK,MAAM,CAAC,IAAK,KAAQ;AAChC,QAAM,CAAC,IAAK,MAAM,CAAC,IAAK,KAAQ;AAChC,QAAM,MAAM,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAChF,SAAO,GAAG,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,IAAI,MAAM,GAAG,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,IAAI,EAAE,CAAC,IAAI,IAAI,MAAM,EAAE,CAAC;AAC1G;;;ACXO,SAAS,sBAAsB,OAAuB;AAC3D,SAAO,MAAM,KAAK,EAAE,YAAY;AAClC;;;AFGA,IAAM,mBAAmB,CAAC,aAAa,YAAY,SAAS,YAAY,aAAa,SAAS;AAC9F,IAAM,mBAAmB,CAAC,gBAAgB,YAAY,SAAS,OAAO;AACtE,IAAM,eAAe;AAGd,SAAS,mBAAmB,GAAwD;AACzF,QAAM,WAAW,GAAG,YAAY;AAChC,QAAM,WAAW,GAAG,YAAY;AAChC,aAAW,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,YAAY,QAAQ,GAAG,CAAC,YAAY,QAAQ,CAAC,GAAY;AACnF,QAAI,CAAC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,OAAO,MAAM,YAAY,MAAM,EAAE,GAAG;AAC/E,YAAM,IAAI,MAAM,6BAA6B,IAAI,0CAA0C;AAAA,IAC7F;AACA,UAAM,SAAS,IAAI,KAAK,CAAC,UAAU,CAAC,aAAa,KAAK,KAAK,CAAC;AAC5D,QAAI,QAAQ;AACV,YAAM,IAAI,MAAM,6BAA6B,IAAI,YAAY,MAAM,gBAAgB,aAAa,MAAM,EAAE;AAAA,IAC1G;AAAA,EACF;AACA,QAAM,YAAY,CAAC,GAAG,UAAU,GAAG,QAAQ,EAAE,KAAK,CAAC,OAAO,OAAO,WAAW,OAAO,QAAQ,KAAK,MAAM,KAAK;AAC3G,MAAI,WAAW;AACb,UAAM,IAAI,MAAM,+CAA+C,SAAS,kCAAkC;AAAA,EAC5G;AACA,MAAI,GAAG,kBAAkB,WAAc,CAAC,MAAM,QAAQ,EAAE,aAAa,KAAK,CAAC,EAAE,cAAc,MAAM,CAAC,MAAM,OAAO,MAAM,YAAY,MAAM,EAAE,IAAI;AAC3I,UAAM,IAAI,MAAM,iFAAiF;AAAA,EACnG;AACA,MAAI,GAAG,cAAc,WAAc,CAAC,MAAM,QAAQ,EAAE,SAAS,KAAK,CAAC,EAAE,UAAU,MAAM,CAAC,MAAM,OAAO,MAAM,YAAY,MAAM,EAAE,IAAI;AAC/H,UAAM,IAAI,MAAM,6EAA6E;AAAA,EAC/F;AAIA,QAAM,aAAa,GAAG,cAAc,CAAC;AACrC,aAAW,CAAC,OAAO,QAAQ,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC1D,eAAW,OAAO,CAAC,eAAe,cAAc,GAAY;AAC1D,YAAM,aAAa,WAAW,GAAG;AACjC,UAAI,eAAe,OAAW;AAC9B,UAAI,OAAO,eAAe,YAAY,CAAC,WAAW,KAAK,GAAG;AACxD,cAAM,IAAI,MAAM,wCAAwC,KAAK,IAAI,GAAG,qCAAqC;AAAA,MAC3G;AACA,2BAAqB,YAAY,wCAAwC,KAAK,IAAI,GAAG,EAAE;AAAA,IACzF;AAAA,EACF;AACA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,GAAG,UAAU,CAAC;AAAA,IACtB,eAAe,GAAG,iBAAiB;AAAA,IACnC,SAAS,GAAG,WAAW;AAAA,IACvB,sBAAsB,GAAG,wBAAwB;AAAA,IACjD,eAAe,GAAG,iBAAiB,CAAC;AAAA,IACpC,WAAW,GAAG,aAAa,CAAC;AAAA,IAC5B,aAAa,GAAG,eAAe;AAAA,IAC/B,eAAe,GAAG,iBAAiB;AAAA,EACrC;AACF;AAKA,IAAM,WAAW;AAIV,SAAS,aAAa,OAAyB;AACpD,SAAO,OAAO,UAAU,YAAY,SAAS,KAAK,KAAK;AACzD;AAIO,SAAS,WAAW,OAAgB,KAAsB;AAC/D,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO;AAClC,SAAO,MAAM,OAAO,CAAC,MAAM,OAAO,MAAM,YAAY,OAAO,MAAM,YAAY,OAAO,MAAM,SAAS,EAAE,MAAM,GAAG,GAAG;AACnH;AAIO,SAAS,iBAAiB,QAA0C;AACzE,SAAO,OAAO,kBAAkB,QAAQ,OAAO,kBAAkB;AACnE;AAIA,IAAM,kBAAkB,oBAAI,IAAI,CAAC,SAAS,aAAa,UAAU,CAAC;AAS3D,SAAS,iBACd,SACA,QACqC;AACrC,QAAM,MAAM,QAAQ;AACpB,QAAMA,WAAU,CAAC,MAAuB,IAAI,cAAc,SAAS,CAAC;AACpE,QAAM,UAAmC,CAAC;AAC1C,aAAW,KAAK,CAAC,GAAG,IAAI,UAAU,GAAG,IAAI,QAAQ,GAAG;AAClD,QAAI,gBAAgB,IAAI,CAAC,KAAK,CAACA,SAAQ,CAAC,EAAG;AAC3C,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,GAAI,SAAQ,CAAC,IAAI,EAAE,KAAK;AAAA,EACpE;AACA,MAAI,OAAO,UAAU,UAAaA,SAAQ,OAAO,EAAG,SAAQ,QAAQ,WAAW,OAAO,OAAO,IAAI,WAAW;AAC5G,SAAO,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AACrD;AAqBA,eAAsB,kBACpB,IACA,SACA,QACA,MAauB;AACvB,QAAM,MAAM,QAAQ;AAMpB,QAAM,cAAc,mBAAmB,IAAI,cAAc,CAAC,GAAG,QAAQ,IAAI,QAAQ;AACjF,aAAW,CAAC,GAAG,KAAK,KAAK,OAAO,QAAQ,WAAW,GAAG;AACpD,QAAI,CAAC,MAAM,SAAU;AACrB,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,OAAO,MAAM,YAAY,EAAE,KAAK,MAAM,GAAI,QAAO,EAAE,IAAI,OAAO,OAAO,GAAG,CAAC,eAAe;AAAA,EAC9F;AACA,aAAW,KAAK,CAAC,GAAG,IAAI,UAAU,GAAG,IAAI,QAAQ,GAAG;AAClD,UAAM,IAAI,OAAO,CAAC;AAClB,UAAM,MAAM,IAAI,OAAO,CAAC,KAAK,IAAI;AACjC,QAAI,OAAO,MAAM,YAAY,EAAE,SAAS,IAAK,QAAO,EAAE,IAAI,OAAO,OAAO,GAAG,CAAC,YAAY,GAAG,cAAc;AAAA,EAC3G;AAIA,MAAI,IAAI,iBAAiB,OAAO,OAAO,UAAU,YAAY,CAAC,aAAa,OAAO,MAAM,KAAK,CAAC,GAAG;AAC/F,WAAO,EAAE,IAAI,OAAO,OAAO,sCAAsC;AAAA,EACnE;AAEA,QAAM,QAAQ,iBAAiB,MAAM;AACrC,MAAI,IAAI,wBAAwB,CAAC,OAAO;AACtC,WAAO,EAAE,IAAI,OAAO,OAAO,4BAA4B;AAAA,EACzD;AAEA,QAAMC,MAAK,KAAK,eACZ,MAAM,2BAA2B,KAAK,YAAY,IAClD,KAAK,MAAM;AACf,QAAM,MAA+B,EAAE,IAAAA,KAAI,QAAQ,QAAQ,SAAS,SAAS,WAAW,KAAK,IAAI;AACjG,aAAW,KAAK,CAAC,GAAG,IAAI,UAAU,GAAG,IAAI,QAAQ,GAAG;AAGlD,QAAI,YAAY,CAAC,GAAG,YAAY,MAAO;AACvC,QAAI,OAAO,OAAO,CAAC,MAAM,SAAU,KAAI,CAAC,IAAK,OAAO,CAAC,EAAa,KAAK;AAAA,EACzE;AACA,MAAI,OAAO,UAAU,OAAW,KAAI,QAAQ,WAAW,OAAO,OAAO,IAAI,WAAW;AACpF,MAAI,KAAK,QAAS,KAAI,UAAU,KAAK;AACrC,MAAI,OAAO,OAAO,UAAU,YAAY,aAAa,OAAO,MAAM,KAAK,CAAC,GAAG;AACzE,QAAI,kBAAkB,sBAAsB,OAAO,KAAK;AAAA,EAC1D;AACA,MAAI,KAAK,gBAAgB,aAAa,mBAAmB;AACvD,QAAI,mBAAmB,KAAK,eAAe;AAC3C,QAAI,kBAAkB,KAAK,eAAe;AAC1C,QAAI,oBAAoB,KAAK;AAAA,EAC/B;AACA,MAAI,KAAK,YAAa,KAAI,cAAc,KAAK;AAK7C,MAAI,OAAO,OAAO,WAAW,YAAY,OAAO,QAAQ;AACtD,QAAI,KAAK,WAAW,CAAC,KAAK,QAAQ,SAAS,OAAO,MAAM,GAAG;AACzD,aAAO,EAAE,IAAI,OAAO,OAAO,gCAAgC;AAAA,IAC7D;AACA,QAAI,SAAS,OAAO;AAAA,EACtB;AAKA,MAAI,MAAO,KAAI,kBAAkB,KAAK;AAEtC,QAAM,MAA4C;AAAA,IAChD,EAAE,GAAG,UAAU,IAAI,gBAAgB,IAAAA,KAAI,OAAO,IAAI;AAAA,EACpD;AACA,MAAI,KAAK,gBAAgB,aAAa,mBAAmB;AACvD,QAAI,KAAK,EAAE,GAAG,UAAU,IAAI,mBAAmB,IAAI,KAAK,eAAe,IAAI,OAAO;AAAA,MAChF,YAAY,KAAK;AAAA,MACjB,uBAAuBA;AAAA,IACzB,EAAE,CAAC;AAAA,EACL;AACA,QAAM,EAAE,UAAU,IAAI,MAAM,GAAG;AAAA,IAC7B;AAAA,IACA,KAAK,eAAe,EAAE,YAAY,QAAQ,KAAK,YAAY,GAAG,IAAI;AAAA,EACpE;AACA,SAAO,EAAE,IAAI,MAAM,IAAAA,KAAI,WAAW,QAAQ,QAAQ,SAAS,SAAS,iBAAiB,QAAQ,KAAK,MAAM,KAAK;AAC/G;AA2BO,SAAS,WACd,OACAC,gBACAC,SAAmC,CAAC,GACpC,aAAwD,CAAC,GAChC;AACzB,SAAO;AAAA,IACL,IAAI,MAAM;AAAA,IACV,MAAM,MAAM;AAAA,IACZ,oBAAoB,MAAM,sBAAsB;AAAA,IAChD,uBAAuB,MAAM,yBAAyB;AAAA,IACtD,OAAO,CAAC,GAAGA,MAAK;AAAA;AAAA,IAEhB;AAAA,IACA,gBAAgB,MAAM,kBAAkB;AAAA,IACxC,kBAAkB,MAAM,oBAAoB;AAAA,IAC5C,WAAW,MAAM,aAAa;AAAA,IAC9B,gBAAgB,MAAM,kBAAkB;AAAA,IACxC,WAAW,MAAM,aAAa;AAAA,IAC9B,eAAAD;AAAA,EACF;AACF;;;AG5RA,IAAM,OAAO,CAAC,MAAgB,QAAqE,CAAC,OAAa;AAAA,EAC/G;AAAA,EAAM,QAAQ,MAAM,UAAU;AAAA,EAAO,SAAS,MAAM,WAAW;AAAA,EAAO,UAAU,MAAM,YAAY;AACpG;AAEA,IAAM,2BAA2B,oBAAI,IAAI;AAAA,EACvC;AAAA,EAAa;AAAA,EAAY;AAAA,EAAS;AAAA,EAAY;AAAA,EAAgB;AAAA,EAC9D;AAAA,EAAS;AAAA,EAAY;AAAA,EAAW;AAAA,EAAS;AAC3C,CAAC;AAED,IAAM,mBAAyC;AAAA,EAC7C,IAAI,KAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,WAAW,KAAK,QAAQ;AAAA,EAAG,UAAU,KAAK,QAAQ;AAAA,EACvG,OAAO,KAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,UAAU,KAAK,QAAQ;AAAA,EAAG,cAAc,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EACnH,WAAW,KAAK,QAAQ;AAAA,EAAG,OAAO,KAAK,MAAM;AAAA,EAAG,UAAU,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAAG,SAAS,KAAK,QAAQ;AAAA,EACpH,QAAQ,KAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,WAAW,KAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EACtF,WAAW,KAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EAAG,aAAa,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAC5G,aAAa,KAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EAAG,8BAA8B,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAC/H,OAAO,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAAG,OAAO,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EACnF,SAAS,KAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EAAG,QAAQ,KAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EACpH,kBAAkB,KAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EAClE,sBAAsB,KAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EAAG,WAAW,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EACrH,iBAAiB,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAAG,mBAAmB,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EACzG,iBAAiB,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAAG,UAAU,KAAK,WAAW,EAAE,UAAU,KAAK,CAAC;AAAA,EACjG,iBAAiB,KAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EACjE,kBAAkB,KAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EAChF,iBAAiB,KAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,EAAG,mBAAmB,KAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EACxH,aAAa,KAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAC7D,cAAc,KAAK,UAAU,EAAE,UAAU,MAAM,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAC5E,aAAa,KAAK,UAAU,EAAE,UAAU,MAAM,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAC3E,aAAa,KAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,YAAY,KAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAC5H,eAAe,KAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAC/D,uBAAuB,KAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AACzE;AAGO,SAAS,gBAAgB,aAA0C;AACxE,QAAM,QAA8B,CAAC;AACrC,aAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,gBAAgB,GAAG;AAC3D,UAAM,IAAI,IAAI,EAAE,GAAG,MAAM,UAAU,yBAAyB,IAAI,IAAI,IAAI,OAAO,KAAK,SAAS;AAAA,EAC/F;AACA,QAAM,QAAQ,CAAC,OAAe,aAA4B;AACxD,UAAM,WAAW,OAAO,OAAO,OAAO,KAAK,IAAI,MAAM,KAAK,IAAI;AAC9D,QAAI,YAAY,CAAC,yBAAyB,IAAI,KAAK,EAAG,OAAM,IAAI,MAAM,qCAAqC,KAAK,0CAA0C;AAC1J,QAAI,YAAY,SAAS,SAAS,SAAU,OAAM,IAAI,MAAM,qCAAqC,KAAK,sCAAsC;AAC5I,WAAO,eAAe,OAAO,OAAO;AAAA,MAClC,OAAO,WAAW,EAAE,GAAG,UAAU,SAAS,IAAI,KAAK,UAAU,EAAE,SAAS,CAAC;AAAA,MACzE,YAAY;AAAA,MAAM,cAAc;AAAA,MAAM,UAAU;AAAA,IAClD,CAAC;AAAA,EACH;AACA,aAAW,SAAS,YAAY,SAAU,OAAM,OAAO,KAAK;AAC5D,aAAW,SAAS,YAAY,SAAU,OAAM,OAAO,IAAI;AAC3D,SAAO,EAAE,MAAM;AACjB;;;ACnDA,IAAME,QAAO,CAAC,MAAgB,QAAqE,CAAC,OAAa;AAAA,EAC/G;AAAA,EACA,QAAQ,MAAM,UAAU;AAAA,EACxB,SAAS,MAAM,WAAW;AAAA,EAC1B,UAAU,MAAM,YAAY;AAC9B;AACA,IAAM,KAAK,MAAYA,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAG9D,IAAM,wBAAgC;AAAA,EAC3C,OAAO;AAAA,IACL,IAAI,GAAG;AAAA,IACP,eAAeA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC/C,aAAaA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC7C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,OAAOA,MAAK,QAAQ;AAAA,IACpB,iBAAiBA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACjD,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,MAAMA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACvC,QAAQA,MAAK,WAAW,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC,gBAAgBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,IAChE,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC3C,WAAWA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,IAC3D,WAAWA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,IAC3D,WAAWA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,IAC3D,WAAWA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,IAC3D,WAAWA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,IAC3D,WAAWA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,IAC3D,YAAYA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,IAC5D,uBAAuBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EACzE;AACF;AAGO,IAAM,gCAAwC;AAAA,EACnD,OAAO;AAAA,IACL,IAAI,GAAG;AAAA,IACP,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,aAAaA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC7C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,QAAQA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACxC,QAAQA,MAAK,WAAW,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC,YAAYA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC9C;AACF;;;AC9CA,IAAMC,QAAO,CAAC,MAAgB,QAAqE,CAAC,OAAa;AAAA,EAC/G;AAAA,EAAM,QAAQ,MAAM,UAAU;AAAA,EAAO,SAAS,MAAM,WAAW;AAAA,EAAO,UAAU,MAAM,YAAY;AACpG;AACA,IAAMC,MAAK,MAAYD,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAG9D,IAAM,4BAAoC,EAAE,OAAO;AAAA,EACxD,IAAIC,IAAG;AAAA,EAAG,WAAWD,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,aAAaA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EACrG,eAAeA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,wBAAwBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAC1H,iBAAiBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,0BAA0BA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC9H,SAASA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,eAAeA,MAAK,MAAM;AAAA,EAAG,QAAQA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EACjH,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,aAAaA,MAAK,QAAQ;AAAA,EAAG,cAAcA,MAAK,QAAQ;AAAA,EACrG,kBAAkBA,MAAK,UAAU,EAAE,UAAU,MAAM,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAChF,oBAAoBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,mBAAmBA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAC3H,QAAQA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,SAASA,MAAK,UAAU,EAAE,UAAU,MAAM,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAClI,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAC3F,EAAE;AAGK,IAAM,mBAA2B,EAAE,OAAO;AAAA,EAC/C,IAAIC,IAAG;AAAA,EAAG,UAAUD,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAChH,aAAaA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,SAASA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,eAAeA,MAAK,MAAM;AAAA,EACtH,eAAeA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,wBAAwBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAC1H,iBAAiBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,0BAA0BA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC9H,iBAAiBA,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,kBAAkBA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EACpH,aAAaA,MAAK,QAAQ;AAAA,EAAG,UAAUA,MAAK,QAAQ;AAAA,EAAG,aAAaA,MAAK,QAAQ;AAAA,EAAG,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AACjI,EAAE;AAGK,IAAM,mBAA2B,EAAE,OAAO;AAAA,EAC/C,IAAIC,IAAG;AAAA,EAAG,SAASD,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,UAAUA,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAC5H,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,SAASA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,QAAQA,MAAK,MAAM;AAAA,EAC7G,wBAAwBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,iBAAiBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAC5I,0BAA0BA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,UAAUA,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EACrH,aAAaA,MAAK,QAAQ;AAAA,EAAG,eAAeA,MAAK,QAAQ;AAAA,EAAG,cAAcA,MAAK,QAAQ;AAAA,EAAG,eAAeA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EACzI,cAAcA,MAAK,QAAQ;AAAA,EAAG,wBAAwBA,MAAK,QAAQ;AAAA,EAAG,QAAQA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC9G,YAAYA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,4BAA4BA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAC3I,mBAAmBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,eAAeA,MAAK,UAAU,EAAE,UAAU,MAAM,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EACnJ,eAAeA,MAAK,UAAU,EAAE,UAAU,MAAM,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,WAAWA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAC5H,WAAWA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,eAAeA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAAG,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAC9J,EAAE;AAGK,IAAM,yBAAiC,EAAE,OAAO;AAAA,EACrD,IAAIC,IAAG;AAAA,EAAG,SAASD,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,EAAG,SAASA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC7G,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,gBAAgBA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC9F,4BAA4BA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,mBAAmBA,MAAK,UAAU,EAAE,UAAU,MAAM,SAAS,KAAK,CAAC;AAAA,EAClI,QAAQA,MAAK,WAAW,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,WAAWA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AACxI,EAAE;AAGK,IAAM,+BAAuC,EAAE,OAAO;AAAA,EAC3D,IAAIC,IAAG;AAAA,EAAG,WAAWD,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,QAAQA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAChG,cAAcA,MAAK,QAAQ;AAAA,EAAG,iBAAiBA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAAG,WAAWA,MAAK,QAAQ;AAC5G,EAAE;;;ACjCF,SAASE,MAAK,MAAgB,QAAqE,CAAC,GAAS;AAC3G,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,MAAM,UAAU;AAAA,IACxB,SAAS,MAAM,WAAW;AAAA,IAC1B,UAAU,MAAM,YAAY;AAAA,EAC9B;AACF;AACA,IAAMC,MAAK,MAAYD,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAKrE,IAAM,SAAiB;AAAA,EACrB,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,OAAOD,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,IACrD,MAAMA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACvC,MAAMA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EACzC;AACF;AAOA,IAAM,cAAsB;AAAA,EAC1B,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,OAAOD,MAAK,UAAU,EAAE,QAAQ,MAAM,SAAS,KAAK,CAAC;AAAA,IACrD,MAAMA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACvC,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC7C;AACF;AAKA,IAAM,eAAuB;AAAA,EAC3B,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,WAAWD,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC3C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,YAAYA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC5C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,MAAMA,MAAK,QAAQ;AAAA,IACnB,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,aAAaA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAC9C,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC7C;AACF;AAIA,IAAM,iBAAyB;AAAA,EAC7B,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,UAAUD,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,aAAaA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC7C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,QAAQA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACxC,UAAUA,MAAK,MAAM;AAAA,IACrB,QAAQA,MAAK,WAAW,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC,YAAYA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC9C;AACF;AAKA,IAAM,wBAAgC;AAAA,EACpC,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,UAAUD,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,aAAaA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC7C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,QAAQA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACxC,UAAUA,MAAK,MAAM;AAAA,IACrB,QAAQA,MAAK,WAAW,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC,YAAYA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC9C;AACF;AAIA,IAAM,qBAA6B;AAAA,EACjC,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,WAAWD,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC3C,aAAaA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC7C,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,UAAUA,MAAK,MAAM;AAAA,IACrB,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC3C,WAAWA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,EAC9C;AACF;AAIA,IAAM,SAAiB;AAAA,EACrB,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,MAAMD,MAAK,QAAQ;AAAA,IACnB,oBAAoBA,MAAK,QAAQ;AAAA,IACjC,uBAAuBA,MAAK,QAAQ;AAAA,IACpC,eAAeA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAChD,sBAAsBA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACvD,mBAAmBA,MAAK,QAAQ;AAAA,IAChC,SAASA,MAAK,QAAQ;AAAA,IACtB,YAAYA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAC7C,cAAcA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAC/C,gBAAgBA,MAAK,QAAQ;AAAA,IAC7B,kBAAkBA,MAAK,QAAQ;AAAA,IAC/B,WAAWA,MAAK,QAAQ;AAAA,IACxB,gBAAgBA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACjD,WAAWA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAC5C,gBAAgBA,MAAK,MAAM;AAAA,IAC3B,gBAAgBA,MAAK,QAAQ,EAAE,UAAU,KAAK,CAAC;AAAA,IAC/C,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC7C;AACF;AAOA,IAAM,QAAgB;AAAA,EACpB,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,SAASD,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC,MAAMA,MAAK,QAAQ;AAAA,IACnB,YAAYA,MAAK,QAAQ;AAAA,IACzB,eAAeA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAChD,OAAOA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACxC,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC3C,QAAQA,MAAK,WAAW,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC7C;AACF;AAIA,IAAM,WAAmB;AAAA,EACvB,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,eAAeD,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC/C,SAASA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC,SAASA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC,OAAOA,MAAK,QAAQ;AAAA,IACpB,UAAUA,MAAK,QAAQ;AAAA,IACvB,QAAQA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACxC,eAAeA,MAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,IAC/D,SAASA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAC1C,UAAUA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAC3C,OAAOA,MAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,IACvD,oBAAoBA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACrD,iBAAiBA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAClD,qBAAqBA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACtD,WAAWA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC7C;AACF;AAGA,IAAM,WAAmB;AAAA,EACvB,OAAO;AAAA,IACL,IAAIC,IAAG;AAAA,IACP,SAASD,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACzC,eAAeA,MAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,IAC/D,IAAIA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IACpC,UAAUA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,IAC1C,SAASA,MAAK,QAAQ;AAAA,IACtB,MAAMA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACvC,WAAWA,MAAK,QAAQ;AAAA,IACxB,WAAWA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IAC5C,YAAYA,MAAK,WAAW,EAAE,UAAU,KAAK,CAAC;AAAA,IAC9C,WAAWA,MAAK,UAAU,EAAE,SAAS,MAAM,UAAU,KAAK,CAAC;AAAA,IAC3D,OAAOA,MAAK,UAAU,EAAE,UAAU,KAAK,CAAC;AAAA,IACxC,QAAQA,MAAK,UAAU,EAAE,SAAS,KAAK,CAAC;AAAA,EAC1C;AACF;AAeO,SAAS,UACd,MACA,MACA,sBAAsB,OACtB,cAAmC,mBAAmB,MAAS,GAC/D,uBAAuB,OACvB,uBAAuB,OACe;AACtC,QAAM,WAAmC,CAAC;AAC1C,MAAI,SAAS,WAAW;AACtB,aAAS,eAAe,gBAAgB,WAAW;AACnD,aAAS,SAAS;AAClB,aAAS,QAAQ;AACjB,aAAS,WAAW;AACpB,aAAS,WAAW;AACpB,aAAS,kBAAkB;AAC3B,aAAS,0BAA0B;AACnC,aAAS,sBAAsB;AAC/B,aAAS,aAAa;AACtB,aAAS,aAAa;AACtB,aAAS,mBAAmB;AAC5B,aAAS,yBAAyB;AAClC,QAAI,qBAAsB,UAAS,iBAAiB;AACpD,QAAI,sBAAsB;AACxB,eAAS,wBAAwB;AACjC,eAAS,qBAAqB;AAAA,IAChC;AAAA,EACF;AACA,MAAI,KAAK,WAAW,QAAS,UAAS,SAAS;AAC/C,MAAI,KAAK,YAAa,UAAS,cAAc;AAC7C,MAAI,oBAAqB,UAAS,eAAe;AACjD,QAAM,SAAmB,EAAE,UAAU,OAAO,CAAC,EAAE;AAC/C,QAAM,QAAiB,CAAC;AACxB,aAAW,MAAM,OAAO,KAAK,QAAQ,GAAG;AACtC,UAAM,EAAE,IAAI,EAAE,MAAM,SAAS,QAAQ,SAAS,QAAQ,SAAS,QAAQ,QAAQ;AAAA,EACjF;AACA,SAAO,EAAE,QAAQ,MAAM;AACzB;;;AC3PA,IAAM,YAAoC;AAAA,EACxC,UAAU;AAAA,IACR,OAAO;AAAA,IACP,MAAM,CAAC,aAAa,WAAW,MAAM;AAAA,IACrC,UAAU,EAAE,SAAS,eAAe,MAAM,WAAW;AAAA,EACvD;AAAA,EACA,cAAc;AAAA,IACZ,OAAO;AAAA,IACP,MAAM,CAAC,aAAa,WAAW,QAAQ,gBAAgB;AAAA,IACvD,UAAU,EAAE,SAAS,eAAe,MAAM,iCAAiC;AAAA,EAC7E;AACF;AAEA,SAAS,aAAsD;AAC7D,SAAO;AAAA,IACL,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,QAAQ;AAAA,MACN,MAAM,EAAE,MAAM,UAAU,OAAO,QAAQ,UAAU,KAAK;AAAA,MACtD,OAAO,EAAE,MAAM,SAAS,OAAO,QAAQ;AAAA,MACvC,WAAW,EAAE,MAAM,UAAU,OAAO,aAAa;AAAA,MACjD,UAAU,EAAE,MAAM,UAAU,OAAO,YAAY;AAAA,MAC/C,OAAO,EAAE,MAAM,UAAU,OAAO,QAAQ;AAAA,MACxC,OAAO,EAAE,MAAM,UAAU,OAAO,SAAS,MAAM,KAAK;AAAA,MACpD,WAAW,EAAE,MAAM,UAAU,OAAO,gBAAgB,MAAM,KAAK;AAAA,MAC/D,UAAU,EAAE,MAAM,UAAU,OAAO,mBAAmB,MAAM,KAAK;AAAA,MACjE,UAAU,EAAE,MAAM,UAAU,OAAO,WAAW;AAAA,MAC9C,OAAO,EAAE,MAAM,QAAQ,OAAO,cAAc;AAAA,MAC5C,SAAS,EAAE,MAAM,UAAU,OAAO,gBAAgB;AAAA,IACpD;AAAA,IACA,UAAU;AAAA,MACR,QAAQ;AAAA,QACN,EAAE,IAAI,aAAa,OAAO,YAAY;AAAA,QACtC,EAAE,IAAI,wBAAwB,OAAO,wBAAwB;AAAA,QAC7D,EAAE,IAAI,kBAAkB,OAAO,iBAAiB;AAAA,QAChD,EAAE,IAAI,eAAe,OAAO,cAAc;AAAA,QAC1C,EAAE,IAAI,YAAY,OAAO,WAAW;AAAA,QACpC,EAAE,IAAI,YAAY,OAAO,WAAW;AAAA,QACpC,EAAE,IAAI,YAAY,OAAO,WAAW;AAAA,MACtC;AAAA,IACF;AAAA,IACA,QAAQ,EAAE,UAAU,MAAM,OAAO,MAAM,MAAM,SAAS;AAAA,EACxD;AACF;AAEA,SAAS,cAAuD;AAC9D,SAAO;AAAA,IACL,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW;AAAA,IACX,QAAQ;AAAA,MACN,MAAM,EAAE,MAAM,UAAU,OAAO,QAAQ,UAAU,KAAK;AAAA,MACtD,QAAQ,EAAE,MAAM,UAAU,OAAO,oBAAoB,MAAM,KAAK;AAAA,MAChE,UAAU,EAAE,MAAM,UAAU,OAAO,YAAY,MAAM,KAAK;AAAA,MAC1D,UAAU,EAAE,MAAM,UAAU,OAAO,YAAY,MAAM,KAAK;AAAA,MAC1D,SAAS,EAAE,MAAM,UAAU,OAAO,WAAW,MAAM,KAAK;AAAA,MACxD,UAAU,EAAE,MAAM,UAAU,OAAO,WAAW;AAAA,MAC9C,OAAO,EAAE,MAAM,UAAU,OAAO,QAAQ;AAAA,IAC1C;AAAA,IACA,QAAQ,EAAE,MAAM,SAAS;AAAA,EAC3B;AACF;AAIO,SAAS,WAAW,OAA+B;AACxD,SAAO;AAAA,IACL,OAAO,EAAE,QAAQ,WAAW,GAAG,SAAS,YAAY,EAAE;AAAA,IACtD,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,IAAI,WAAW,OAAO,YAAY,cAAc,OAAO,EAAE;AAAA,IAClG,WAAW;AAAA,EACb;AACF;;;AC1EA,IAAM,qBAA2E;AAAA,EAC/E,aAAa;AAAA,EACb,MAAM,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA,EACpB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,YAAY;AACd;AAEA,SAAS,sBAAsB,MAAiE;AAC9F,QAAM,OAAO;AAAA;AAAA;AAAA,EAAgB,IAAI;AACjC,SAAO;AAAA,IACL,mBAAmB;AAAA,MACjB,SAAS;AAAA,MACT,MAAM,iCAAiC,IAAI;AAAA;AAAA;AAAA;AAAA,IAC7C;AAAA,IACA,qBAAqB;AAAA,MACnB,SAAS,cAAc,IAAI;AAAA,MAC3B,MAAM;AAAA;AAAA,sFAA4G,IAAI;AAAA,IACxH;AAAA,IACA,WAAW;AAAA,MACT,SAAS,QAAQ,IAAI;AAAA,MACrB,MAAM;AAAA;AAAA,iEAAuF,IAAI;AAAA,IACnG;AAAA,IACA,kBAAkB;AAAA,MAChB,SAAS,cAAc,IAAI;AAAA,MAC3B,MAAM;AAAA;AAAA,aAAmC,IAAI,6CAA6C,IAAI;AAAA,IAChG;AAAA,EACF;AACF;AAIO,SAAS,eAAe,QAAgD;AAC7E,QAAM,SAAS,OAAO;AACtB,QAAM,SAAS,OAAO;AACtB,QAAM,SAAS,OAAO,UAAU,CAAC;AACjC,QAAM,aAAa;AAAA,IACjB,GAAG;AAAA,IACH,GAAI,OAAO,cAAc,CAAC;AAAA,IAC1B,iBACE,OAAO,YAAY,mBAAmB,GAAG,OAAO,IAAI;AAAA,EACxD;AACA,QAAM,MAA+B;AAAA,IACnC,IAAI,OAAO;AAAA,IACX,MAAM,OAAO;AAAA,IACb,oBAAoB,QAAQ,iBAAiB;AAAA,IAC7C,uBAAuB,QAAQ,yBAAyB;AAAA,IACxD,mBAAmB,QAAQ,qBAAqB;AAAA,IAChD,SAAS,QAAQ,WAAW,QAAQ,qBAAqB;AAAA,IACzD,gBAAgB,OAAO,kBAAkB;AAAA,IACzC,kBAAkB,OAAO,oBAAoB;AAAA,IAC7C,WAAW,OAAO,aAAa;AAAA,IAC/B,gBAAgB,QAAQ,aAAa,sBAAsB,OAAO,IAAI;AAAA,IACtE,gBAAgB;AAAA,EAClB;AACA,MAAI,QAAQ,WAAY,KAAI,aAAa,OAAO;AAChD,MAAI,OAAO,eAAgB,KAAI,iBAAiB,OAAO;AACvD,MAAI,OAAO,UAAW,KAAI,YAAY,OAAO;AAC7C,SAAO;AACT;;;ACtDO,SAAS,YAAY,MAAmB,MAA6C;AAC1F,QAAM,IAAI,QAAQ,CAAC;AACnB,QAAM,SAAS,EAAE,WAAW,SAAS,QAAQ,UAAU;AACvD,MAAI,WAAW,WAAW,WAAW,SAAS;AAC5C,UAAM,IAAI,MAAM,oEAA+D,KAAK,UAAU,EAAE,MAAM,CAAC,EAAE;AAAA,EAC3G;AACA,QAAM,QAAQ,EAAE,SAAS;AACzB,MAAI,OAAO,UAAU,YAAY,UAAU,IAAI;AAC7C,UAAM,IAAI,MAAM,sDAAsD;AAAA,EACxE;AACA,QAAM,SAAS,EAAE,UAAU,CAAC,eAAe,UAAU,OAAO;AAC5D,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,KAAK,CAAC,OAAO,MAAM,CAAC,MAAM,OAAO,MAAM,YAAY,MAAM,EAAE,GAAG;AAC5G,UAAM,IAAI,MAAM,sEAAsE;AAAA,EACxF;AACA,QAAM,YAAY,OAAO,OAAO,SAAS,CAAC;AAC1C,QAAME,eAAc,EAAE,eAAe,WAAW;AAChD,SAAO,EAAE,QAAQ,OAAO,QAAQ,WAAW,aAAAA,aAAY;AACzD;AAIO,SAAS,cAAc,SAAkC,MAA4B;AAC1F,QAAM,MAAM,QAAQ,KAAK,KAAK;AAC9B,SAAO,OAAO,QAAQ,YAAY,KAAK,OAAO,SAAS,GAAG,IAAI,MAAO,KAAK,OAAO,CAAC;AACpF;AAGO,SAAS,YAAY,MAAc,MAA6B;AACrE,SAAO,SAAS,KAAK;AACvB;AA0BO,SAAS,cAAc,KAAqC;AACjE,QAAM,EAAE,KAAK,IAAI;AACjB,MAAI,CAAC,KAAK,OAAO,SAAS,IAAI,OAAO,GAAG;AACtC,WAAO,EAAE,IAAI,OAAO,QAAQ,KAAK,OAAO,wBAAwB,KAAK,OAAO,KAAK,IAAI,CAAC,GAAG;AAAA,EAC3F;AACA,MAAI,IAAI,YAAY,IAAI,UAAU;AAChC,WAAO,EAAE,IAAI,OAAO,QAAQ,KAAK,OAAO,kCAAkC;AAAA,EAC5E;AACA,MAAI,IAAI,iBAAiB,CAAC,IAAI,cAAc;AAC1C,WAAO,EAAE,IAAI,OAAO,QAAQ,KAAK,OAAO,uEAAuE;AAAA,EACjH;AACA,QAAM,eAAe,IAAI,YAAY,KAAK,aAAa,IAAI,sBAAsB,KAAK;AACtF,MAAI,KAAK,eAAe,gBAAgB,CAAC,IAAI,cAAc;AACzD,WAAO,EAAE,IAAI,OAAO,QAAQ,KAAK,OAAO,6CAA6C,KAAK,SAAS,GAAG;AAAA,EACxG;AACA,SAAO,EAAE,IAAI,KAAK;AACpB;AAaA,eAAsB,eAAe,IAAiB,MAA2C;AAC/F,MAAI;AACF,UAAM,QAAQ,MAAM,GAAG,QAAQ,IAAI,IAAI;AACvC,WAAO,OAAO,UAAU,YAAY,UAAU,KAAK,QAAQ;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AChGA,IAAM,iBAAiB;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAM,mBAAmB,CAAC,aAAa,wBAAwB,gBAAgB;AAC/E,IAAM,qBAAqB,CAAC,wBAAwB,kBAAkB,aAAa;AAS5E,SAAS,gBAAgB,GAAkD;AAChF,QAAM,gBAAgB,CAAC,GAAG;AAC1B,QAAM,SAAS,GAAG,UAAU,CAAC,GAAG,cAAc;AAC9C,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,WAAW,KAAK,CAAC,OAAO,MAAM,CAAC,MAAM,OAAO,MAAM,YAAY,MAAM,EAAE,GAAG;AAC5G,UAAM,IAAI,MAAM,4EAA4E;AAAA,EAC9F;AACA,MAAI,IAAI,IAAI,MAAM,EAAE,SAAS,OAAO,QAAQ;AAC1C,UAAM,IAAI,MAAM,wDAAwD;AAAA,EAC1E;AACA,QAAM,UAAU,GAAG,WAAY,OAAO,CAAC;AACvC,MAAI,CAAC,OAAO,SAAS,OAAO,GAAG;AAC7B,UAAM,IAAI,MAAM,oCAAoC,OAAO,4BAA4B;AAAA,EACzF;AACA,QAAM,eAAe,GAAG,iBAAiB,gBAAgB,CAAC,GAAG,gBAAgB,IAAI,CAAC;AAClF,QAAM,iBAAiB,GAAG,mBAAmB,gBAAgB,CAAC,GAAG,kBAAkB,IAAI,CAAC;AACxF,aAAW,CAAC,MAAM,MAAM,KAAK;AAAA,IAC3B,CAAC,gBAAgB,YAAY;AAAA,IAC7B,CAAC,kBAAkB,cAAc;AAAA,EACnC,GAAY;AACV,eAAW,KAAK,QAAQ;AACtB,UAAI,CAAC,OAAO,SAAS,CAAC,EAAG,OAAM,IAAI,MAAM,0BAA0B,IAAI,MAAM,CAAC,4BAA4B;AAAA,IAC5G;AAAA,EACF;AACA,SAAO,EAAE,QAAQ,cAAc,gBAAgB,QAAQ;AACzD;AAGO,SAAS,WAAW,QAAgB,GAA6B;AACtE,SAAO,EAAE,OAAO,QAAQ,MAAM;AAChC;AAQO,SAAS,cAAc,MAAc,IAAY,GAA8B;AACpF,QAAM,KAAK,EAAE,OAAO,QAAQ,IAAI;AAChC,QAAM,KAAK,EAAE,OAAO,QAAQ,EAAE;AAC9B,SAAO,MAAM,KAAK,MAAM,KAAK,MAAM;AACrC;AAGO,SAAS,QAAQ,QAAgB,GAA8B;AACpE,SAAO,EAAE,aAAa,SAAS,MAAM;AACvC;AAGO,SAAS,WAAW,QAAgB,GAA8B;AACvE,SAAO,EAAE,eAAe,SAAS,MAAM;AACzC;;;AC5EO,IAAM,qBAA2C;AAAA,EACtD,MAAM;AAAA,IACJ,UAAU;AAAA,IACV,eAAe;AAAA,IACf,sBAAsB;AAAA,IACtB,aAAa;AAAA,IACb,SAAS;AAAA,IACT,SAAS;AAAA,IACT,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AAAA,EACA,OAAO;AAAA,IACL,WAAW;AAAA,IACX,cAAc;AAAA,IACd,WAAW;AAAA,IACX,iBAAiB;AAAA,EACnB;AAAA,EACA,YAAY;AAAA,IACV,WAAW;AAAA,IACX,UAAU;AAAA,IACV,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,SAAS;AAAA,IACT,WAAW;AAAA,IACX,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,IACP,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,kBAAkB;AAAA,IAClB,qBAAqB;AAAA,EACvB;AAAA,EACA,WAAW;AAAA,IACT,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,IACN,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,uBAAuB;AAAA,IACvB,cAAc;AAAA,IACd,SAAS;AAAA,IACT,oBAAoB;AAAA,IACpB,UAAU;AAAA,IACV,eAAe;AAAA,IACf,UAAU;AAAA,IACV,UAAU;AAAA,IACV,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,UAAU;AAAA,EACZ;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,SAAS;AAAA,IACT,eAAe;AAAA,IACf,UAAU;AAAA,IACV,WAAW;AAAA,IACX,MAAM;AAAA,IACN,OAAO;AAAA,IACP,aAAa;AAAA,IACb,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,cAAc;AAAA,IACZ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,OAAO;AAAA,IACP,MAAM;AAAA,IACN,WAAW;AAAA,IACX,SAAS;AAAA,IACT,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,MAAM;AAAA,IACN,WAAW,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK;AAAA,EAC7D;AAAA,EACA,OAAO;AAAA,IACL,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,WAAW;AAAA,EACb;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SAAS;AAAA,IACT,OAAO;AAAA,IACP,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV;AAAA,EACA,WAAW;AAAA,IACT,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,UAAU;AAAA,IACV,SAAS;AAAA,IACT,MAAM;AAAA,IACN,OAAO;AAAA,IACP,SAAS;AAAA,IACT,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,UAAU;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,SAAS;AAAA,IACP,OAAO;AAAA,IACP,sBAAsB;AAAA,IACtB,SAAS;AAAA,IACT,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,wBAAwB;AAAA,IACxB,aAAa;AAAA,IACb,WAAW;AAAA,IACX,WAAW;AAAA,IACX,aAAa;AAAA,IACb,cAAc;AAAA,IACd,gBAAgB;AAAA,EAClB;AAAA,EACA,SAAS;AAAA,IACP,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,WAAW;AAAA,IACX,MAAM;AAAA,IACN,gBAAgB;AAAA,IAChB,WAAW;AAAA,IACX,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,UAAU;AAAA,IACV,SAAS;AAAA,IACT,aAAa;AAAA,IACb,gBAAgB;AAAA,IAChB,kBAAkB;AAAA,IAClB,UAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,SAAS;AAAA,IACT,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,eAAe;AAAA,IACf,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,eAAe;AAAA,IACf,iBAAiB;AAAA,IACjB,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV;AACF;;;ACxNO,IAAM,sBAA6C;AAAA,EACxD,SAAS;AAAA,EACT,OAAO;AAAA,EACP,SAAS;AACX;AAEO,IAAM,oBAAyC;AAAA,EACpD,MAAM;AAAA,IACJ,QAAQ;AAAA,IACR,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,mBAAmB;AAAA,EACrB;AAAA,EACA,SAAS;AAAA,IACP,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AAAA,EACA,SAAS;AAAA,IACP,aAAa;AAAA,IACb,WAAW;AAAA,IACX,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,SAAS;AAAA,EACX;AAAA,EACA,MAAM;AAAA,IACJ,OAAO;AAAA,IACP,gBAAgB;AAAA,IAChB,YAAY;AAAA,EACd;AAAA,EACA,UAAU;AAAA,IACR,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,MAAM;AAAA,IACJ,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AACF;AAEO,IAAM,uBAA+C;AAAA,EAC1D,YAAY;AAAA,EACZ,SAAS;AAAA,IACP,SAAS;AAAA,IACT,cAAc;AAAA,EAChB;AAAA,EACA,aAAa;AAAA,IACX,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,uBAAuB;AAAA,IACvB,OAAO;AAAA,IACP,UAAU;AAAA,IACV,cAAc;AAAA,IACd,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,UAAU;AAAA,IACV,UAAU;AAAA,IACV,cAAc;AAAA,IACd,YAAY;AAAA,EACd;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,EACX;AAAA,EACA,OAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,eAAe;AAAA,IACf,MAAM;AAAA,IACN,UAAU;AAAA,IACV,WAAW;AAAA,IACX,aAAa;AAAA,IACb,SAAS;AAAA,IACT,UAAU;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,cAAc;AAAA,IACd,aAAa;AAAA,IACb,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA,YAAY;AAAA,IACV,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,SAAS;AAAA,IACT,SAAS;AAAA,IACT,cAAc;AAAA,IACd,UAAU;AAAA,EACZ;AACF;;;ACnGO,IAAM,uBAAoC;AAAA,EAC/C,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AACT;AAEA,IAAM,WAAW,CAAC,UAChB,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAErE,SAAS,UAAa,MAAS,OAAgB,MAAiB;AAC9D,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI,UAAU,OAAW,QAAO;AAChC,QAAI,OAAO,UAAU,SAAU,OAAM,IAAI,MAAM,GAAG,IAAI,oBAAoB;AAC1E,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,IAAI,GAAG;AACvB,QAAI,UAAU,OAAW,QAAO,CAAC,GAAG,IAAI;AACxC,QAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,MAAM,CAAC,SAAS,OAAO,SAAS,QAAQ,GAAG;AAC7E,YAAM,IAAI,MAAM,GAAG,IAAI,+BAA+B;AAAA,IACxD;AACA,WAAO,CAAC,GAAG,KAAK;AAAA,EAClB;AACA,MAAI,CAAC,SAAS,IAAI,EAAG,QAAO;AAC5B,MAAI,UAAU,UAAa,CAAC,SAAS,KAAK,EAAG,OAAM,IAAI,MAAM,GAAG,IAAI,qBAAqB;AACzF,QAAM,YAAY;AAClB,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,GAAG;AAC/C,WAAO,GAAG,IAAI,UAAU,OAAO,YAAY,GAAG,GAAG,GAAG,IAAI,IAAI,GAAG,EAAE;AAAA,EACnE;AACA,SAAO;AACT;AAGO,SAAS,mBAAmB,OAAuC;AACxE,SAAO,UAAU,sBAAsB,OAAO,oBAAoB;AACpE;AAGO,SAAS,kBACd,UACA,QACQ;AACR,SAAO,SAAS;AAAA,IAAQ;AAAA,IAA+B,CAAC,OAAO,QAC7D,OAAO,UAAU,eAAe,KAAK,QAAQ,GAAG,IAAI,OAAO,OAAO,GAAG,CAAC,IAAI;AAAA,EAC5E;AACF;;;ACnDO,IAAM,qCAAqC;AAmClD,IAAM,qBAAuD;AAAA,EAC3D,WAAW;AAAA,EACX,UAAU;AAAA,EACV,OAAO;AAAA,EACP,UAAU;AAAA,EACV,cAAc;AAAA,EACd,WAAW;AAAA,EACX,UAAU;AAAA,EACV,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AACT;AAEA,SAAS,SAASC,KAAoB;AACpC,QAAMC,QAAOD,IAAG,QAAQ,sBAAsB,OAAO,EAAE,QAAQ,UAAU,GAAG,EAAE,KAAK;AACnF,SAAOC,QAAO,GAAGA,MAAK,CAAC,EAAG,YAAY,CAAC,GAAGA,MAAK,MAAM,CAAC,CAAC,KAAKD;AAC9D;AAEA,SAAS,gBAAgB,SAA4C;AACnE,MAAI;AACF,WAAO,QAAQ,IAAI,KAAK,QAAQ,EAAE;AAAA,EACpC,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEA,SAAS,gBAAgBA,KAAY,KAAsC;AAIzE,MAAI,OAAO,CAAC,UAAU,SAAS,OAAO,MAAM,EAAE,SAAS,IAAI,IAAI,EAAG,QAAO,IAAI;AAC7E,SAAOA,QAAO,UAAU,UAAUA,QAAO,aAAa,QAAQ;AAChE;AAGO,SAAS,sBACd,SACA,cAAmC,QAAQ,aACvB;AACpB,QAAM,OAAO,gBAAgB,OAAO;AACpC,SAAO,CAAC,GAAG,YAAY,UAAU,GAAG,YAAY,QAAQ,EAAE,IAAI,CAACA,KAAI,UAAU;AAC3E,UAAM,MAAM,KAAKA,GAAE;AACnB,UAAM,aAAa,YAAY,WAAWA,GAAE;AAC5C,UAAM,OAAO,gBAAgBA,KAAI,GAAG;AACpC,WAAO;AAAA,MACL,IAAAA;AAAA,MACA,OAAO,KAAK,SAAS,mBAAmBA,GAAE,KAAK,SAASA,GAAE;AAAA,MAC1D;AAAA,MACA,UAAU,YAAY,SAAS,SAASA,GAAE;AAAA,MAC1C;AAAA,MACA,WAAW,YAAY,OAAOA,GAAE,KAAK,YAAY;AAAA,MACjD,GAAI,SAAS,UAAU,KAAK,UAAU,EAAE,SAAS,CAAC,GAAG,IAAI,OAAO,EAAE,IAAI,CAAC;AAAA,MACvE,GAAI,aAAa,EAAE,YAAY,EAAE,GAAG,WAAW,EAAE,IAAI,CAAC;AAAA,MACtD,GAAI,SAAS,UAAU,EAAE,eAAe,UAAmB,IAAI,CAAC;AAAA,IAClE;AAAA,EACF,CAAC;AACH;AAGO,SAAS,2BACd,KACA,WACoB;AACpB,MAAI,CAAC,UAAU,QAAS,QAAO,CAAC;AAChC,QAAM,MAAM,IAAI,KAAK,UAAU,IAAI;AACnC,SAAO,CAAC,GAAG,UAAU,UAAU,GAAG,UAAU,QAAQ,EAAE,IAAI,CAACA,KAAI,UAAU;AACvE,UAAM,QAAQ,IAAI,OAAOA,GAAE;AAC3B,WAAO;AAAA,MACL,IAAAA;AAAA,MACA,OAAO,MAAM,SAAS,SAASA,GAAE;AAAA,MACjC,MAAM,MAAM;AAAA,MACZ,UAAU,UAAU,SAAS,SAASA,GAAE;AAAA,MACxC;AAAA,MACA,WAAW,UAAU,OAAOA,GAAE,KAAK,UAAU;AAAA,MAC7C,GAAI,MAAM,UAAU,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,EAAE,IAAI,CAAC;AAAA,MACvD,GAAIA,QAAO,IAAI,cAAc,MAAM,SAAS,UAAU,EAAE,eAAe,UAAmB,IAAI,CAAC;AAAA,IACjG;AAAA,EACF,CAAC;AACH;AAGO,SAAS,oBACd,SACA,YAAqC,QAAQ,WACzB;AACpB,SAAO,2BAA2B,QAAQ,KAAK,SAAS;AAC1D;AAOO,SAAS,yBACd,SACA,MACA,cAAmC,QAAQ,aACjB;AAC1B,SAAO;AAAA,IACL,eAAe;AAAA,IACf;AAAA,IACA,QAAQ,SAAS,SACb,sBAAsB,SAAS,WAAW,IAC1C,oBAAoB,OAAO;AAAA,EACjC;AACF;;;AC5IA,IAAME,oBAAmB,CAAC,QAAQ,SAAS,YAAY,QAAQ;AAC/D,IAAMC,oBAAmB,CAAC,mBAAmB,cAAc,eAAe;AAGnE,SAAS,uBACd,OACA,KACyB;AACzB,QAAM,OAAO,OAAO,QAAQ;AAC5B,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,UAAU,CAAC;AAAA,MACX,UAAU,CAAC;AAAA,MACX,QAAQ,CAAC;AAAA,MACT,eAAe;AAAA,MACf,SAAS;AAAA,IACX;AAAA,EACF;AACA,QAAM,MAAM,IAAI,OAAO,MAAM,IAAI;AACjC,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mDAAmD,IAAI,GAAG;AACpF,QAAM,WAAW,MAAM,aAAa,SAAS,wBAAwBD,oBAAmB,CAAC;AACzF,QAAM,WAAW,MAAM,aAAa,SAAS,wBAAwBC,oBAAmB,CAAC;AACzF,aAAW,CAAC,MAAM,MAAM,KAAK,CAAC,CAAC,YAAY,QAAQ,GAAG,CAAC,YAAY,QAAQ,CAAC,GAAY;AACtF,QAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,CAAC,OAAO,MAAM,CAAC,UAAU,OAAO,UAAU,YAAY,UAAU,EAAE,GAAG;AACjG,YAAM,IAAI,MAAM,2BAA2B,IAAI,0CAA0C;AAAA,IAC3F;AAAA,EACF;AACA,QAAM,aAAa,CAAC,GAAG,UAAU,GAAG,QAAQ,EAAE,OAAO,CAAC,OAAO,OAAO,WAAW,OAAO,QAAQ,KAAK,MAAM,KAAK;AAC9G,MAAI,WAAW,OAAQ,OAAM,IAAI,MAAM,oDAAoD,WAAW,CAAC,CAAC,GAAG;AAC3G,QAAM,UAAU,CAAC,GAAG,UAAU,GAAG,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,KAAK,CAAC;AAC/E,MAAI,QAAQ,OAAQ,OAAM,IAAI,MAAM,mCAAmC,QAAQ,CAAC,CAAC,kCAAkC,IAAI,GAAG;AAC1H,QAAM,kBAAkB,OAAO,QAAQ,IAAI,MAAM,EAC9C,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,MAAM,QAAQ,EACpC,IAAI,CAAC,CAAC,KAAK,MAAM,KAAK,EACtB,OAAO,CAAC,UAAU,CAAC,SAAS,SAAS,KAAK,CAAC;AAC9C,MAAI,gBAAgB,QAAQ;AAC1B,UAAM,IAAI,MAAM,sEAAsE,gBAAgB,CAAC,CAAC,GAAG;AAAA,EAC7G;AACA,QAAM,sBAAsB,SAAS,KAAK,CAAC,UACzC,CAAC,CAAC,UAAU,SAAS,OAAO,MAAM,EAAE,SAAS,IAAI,OAAO,KAAK,EAAG,IAAI,CAAC;AACvE,MAAI,qBAAqB;AACvB,UAAM,IAAI,MAAM,4CAA4C,mBAAmB,uBAAuB;AAAA,EACxG;AACA,MAAI,SAAS,WAAW,EAAG,OAAM,IAAI,MAAM,qDAAqD;AAChG,QAAM,gBAAgB,MAAM,iBAAiB;AAC7C,QAAM,UAAU,MAAM,WAAW;AACjC,MAAI,CAAC,OAAO,cAAc,aAAa,KAAK,gBAAgB,KAAK,gBAAgB,OAAO;AACtF,UAAM,IAAI,MAAM,2EAA2E;AAAA,EAC7F;AACA,MAAI,CAAC,OAAO,cAAc,OAAO,KAAK,UAAU,QAAQ,UAAU,QAAQ;AACxE,UAAM,IAAI,MAAM,yEAAyE;AAAA,EAC3F;AACA,aAAW,CAAC,OAAO,GAAG,KAAK,OAAO,QAAQ,MAAM,UAAU,CAAC,CAAC,GAAG;AAC7D,QAAI,CAAC,CAAC,GAAG,UAAU,GAAG,QAAQ,EAAE,SAAS,KAAK,KAAK,CAAC,OAAO,cAAc,GAAG,KAAK,MAAM,KAAK,MAAM,OAAO;AACvG,YAAM,IAAI,MAAM,kCAAkC,KAAK,8DAA8D;AAAA,IACvH;AAAA,EACF;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,MAAM,UAAU,CAAC;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AACF;AAGO,SAAS,gBACd,KACA,WAC4C;AAC5C,SAAO,2BAA2B,KAAK,SAAS;AAClD;;;ACxEA,IAAM,OAAO;AACb,IAAM,QAAQ;AACd,IAAM,UAAU;AAEhB,SAAS,oBAAoB,MAK1B;AACD,QAAM,YAAY,KAAK,OAAO,KAAK,CAAC,MAAM,UAAU,KAAK,OAAO,QAAQ,IAAI,MAAM,KAAK;AACvF,QAAM,UAAU,KAAK,OAAO,KAAK,CAAC,SAChC,CAAC,MAAM,KAAK,IAAI,KAAK,CAAC,KAAK,IAAI,OAAO,MAAM,IAAI,MAAM,KAAK,SAAS,CAAC,KAAK,OAAO,IAAI,IAAI,MAAM;AACjG,MAAI,aAAa,SAAS;AACxB,UAAM,IAAI,MAAM,GAAG,KAAK,IAAI,mDAAmD;AAAA,EACjF;AACF;AAIO,SAAS,eAAe,QAAuB,KAA2B;AAC/E,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,UAAmC,CAAC;AAC1C,aAAW,UAAU,OAAO,SAAS,WAAW,CAAC,GAAG;AAClD,QAAI,CAAC,KAAK,KAAK,OAAO,EAAE,GAAG;AACzB,YAAM,IAAI,MAAM,yEAAoE,KAAK,UAAU,OAAO,EAAE,CAAC,EAAE;AAAA,IACjH;AACA,QAAI,KAAK,IAAI,OAAO,EAAE,EAAG,OAAM,IAAI,MAAM,oDAAoD,OAAO,EAAE,GAAG;AACzG,SAAK,IAAI,OAAO,EAAE;AAClB,QAAI;AACJ,QAAI;AACF,YAAM,IAAI,IAAI,OAAO,GAAG;AAAA,IAC1B,QAAQ;AACN,YAAM,IAAI,MAAM,iCAAiC,OAAO,EAAE,+BAA+B;AAAA,IAC3F;AACA,UAAM,QAAQ,IAAI,aAAa,eAAe,IAAI,aAAa,eAAe,IAAI,aAAa;AAC/F,QAAI,IAAI,aAAa,YAAY,EAAE,SAAS,IAAI,aAAa,UAAU;AACrE,YAAM,IAAI,MAAM,iCAAiC,OAAO,EAAE,2DAA2D;AAAA,IACvH;AACA,UAAM,SAAS,OAAO;AACtB,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,UAAU,CAAC,CAAC,GAAG;AACxD,UAAI,CAAC,MAAM,KAAK,IAAI,KAAK,MAAM,WAAW,KAAK,MAAM,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,IAAI,CAAC,GAAG;AACtF,cAAM,IAAI;AAAA,UACR,iCAAiC,OAAO,EAAE,WAAW,IAAI;AAAA,QAC3D;AAAA,MACF;AACA,YAAM,MAAM,IAAI,OAAO,MAAM,IAAI;AACjC,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,iCAAiC,OAAO,EAAE,qCAAqC,IAAI,GAAG;AAChH,YAAM,UAAU,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,KAAK,CAAC;AAC1D,UAAI,QAAQ,SAAS,GAAG;AACtB,cAAM,IAAI;AAAA,UACR,iCAAiC,OAAO,EAAE,WAAW,IAAI,KAAK,QAAQ,IAAI,CAAC,UAAU,IAAI,KAAK,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,QAE/G;AAAA,MACF;AACA,YAAM,YAAY,IAAI,aAAa;AACnC,UAAI,CAAC,MAAM,SAAS,SAAS,GAAG;AAC9B,cAAM,IAAI;AAAA,UACR,iCAAiC,OAAO,EAAE,WAAW,IAAI,uCAAuC,SAAS;AAAA,QAC3G;AAAA,MACF;AAAA,IACF;AACA,UAAM,aAAa,OAAO,YAAY,KAAK,KAAK,iBAAiB,OAAO,GAAG,WAAW,KAAK,GAAG,CAAC;AAC/F,QAAI,CAAC,iCAAiC,KAAK,UAAU,GAAG;AACtD,YAAM,IAAI,MAAM,iCAAiC,OAAO,EAAE,6CAA6C;AAAA,IACzG;AACA,UAAM,UAAU,OAAO,SAAS,KAAK;AACrC,QAAI,WAAW,CAAC,QAAQ,KAAK,OAAO,GAAG;AACrC,YAAM,IAAI;AAAA,QACR,iCAAiC,OAAO,EAAE;AAAA,MAC5C;AAAA,IACF;AACA,UAAM,cAAc,OAAO,eAAe,CAAC;AAC3C,wBAAoB;AAAA,MAClB,MAAM,iCAAiC,OAAO,EAAE;AAAA,MAChD,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,IACF,CAAC;AACD,YAAQ,KAAK;AAAA,MACX,IAAI,OAAO;AAAA,MACX,MAAM,OAAO,MAAM,KAAK,KAAK,OAAO;AAAA,MACpC,KAAK,IAAI;AAAA,MACT,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B;AAAA,MACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACH;AACA,QAAM,YAAY,oBAAI,IAAY;AAClC,QAAM,UAAmC,CAAC;AAC1C,aAAW,UAAU,OAAO,SAAS,WAAW,CAAC,GAAG;AAClD,QAAI,CAAC,KAAK,KAAK,OAAO,EAAE,GAAG;AACzB,YAAM,IAAI,MAAM,yEAAoE,KAAK,UAAU,OAAO,EAAE,CAAC,EAAE;AAAA,IACjH;AACA,QAAI,UAAU,IAAI,OAAO,EAAE,GAAG;AAC5B,YAAM,IAAI,MAAM,oDAAoD,OAAO,EAAE,GAAG;AAAA,IAClF;AACA,cAAU,IAAI,OAAO,EAAE;AACvB,UAAM,UAAU,OAAO,QAAQ,OAAO,UAAU,CAAC,CAAC;AAClD,QAAI,QAAQ,WAAW,GAAG;AACxB,YAAM,IAAI,MAAM,iCAAiC,OAAO,EAAE,4CAA4C;AAAA,IACxG;AACA,eAAW,CAAC,MAAM,KAAK,KAAK,SAAS;AACnC,UAAI,CAAC,MAAM,KAAK,IAAI,KAAK,MAAM,WAAW,KAAK,MAAM,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,IAAI,CAAC,GAAG;AACtF,cAAM,IAAI;AAAA,UACR,iCAAiC,OAAO,EAAE,WAAW,IAAI;AAAA,QAC3D;AAAA,MACF;AACA,YAAM,MAAM,IAAI,OAAO,MAAM,IAAI;AACjC,UAAI,CAAC,KAAK;AACR,cAAM,IAAI,MAAM,iCAAiC,OAAO,EAAE,oCAAoC,IAAI,GAAG;AAAA,MACvG;AACA,YAAM,UAAU,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,OAAO,KAAK,CAAC;AAC1D,UAAI,QAAQ,SAAS,GAAG;AACtB,cAAM,IAAI;AAAA,UACR,iCAAiC,OAAO,EAAE,WAAW,IAAI,KACtD,QAAQ,IAAI,CAAC,UAAU,IAAI,KAAK,GAAG,EAAE,KAAK,IAAI,CAAC;AAAA,QACpD;AAAA,MACF;AACA,YAAM,YAAY,IAAI,aAAa;AACnC,UAAI,CAAC,MAAM,SAAS,SAAS,GAAG;AAC9B,cAAM,IAAI;AAAA,UACR,iCAAiC,OAAO,EAAE,WAAW,IAAI,uCAAuC,SAAS;AAAA,QAC3G;AAAA,MACF;AAAA,IACF;AACA,UAAM,cAAc,OAAO,eAAe,CAAC;AAC3C,wBAAoB;AAAA,MAClB,MAAM,iCAAiC,OAAO,EAAE;AAAA,MAChD,QAAQ;AAAA,MACR;AAAA,MACA,QAAQ,OAAO;AAAA,IACjB,CAAC;AACD,YAAQ,KAAK,EAAE,IAAI,OAAO,IAAI,QAAQ,OAAO,QAAQ,YAAY,CAAC;AAAA,EACpE;AACA,SAAO,EAAE,SAAS,QAAQ;AAC5B;;;AC/IA,IAAMC,QAAO;AACb,IAAM,cAAc;AAGb,SAAS,qBACd,OAC8B;AAC9B,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,CAACA,MAAK,KAAK,MAAM,QAAQ,GAAG;AAC9B,UAAM,IAAI,MAAM,oEAAoE;AAAA,EACtF;AACA,MAAI,MAAM,eAAe,UAAU,MAAM,eAAe,QAAQ;AAC9D,UAAM,IAAI,MAAM,kEAAkE;AAAA,EACpF;AACA,QAAM,aAAa,MAAM,YAAY,KAAK,KAAK;AAC/C,MAAI,CAAC,YAAY,KAAK,UAAU,GAAG;AACjC,UAAM,IAAI,MAAM,wEAAwE;AAAA,EAC1F;AACA,SAAO,EAAE,UAAU,MAAM,UAAU,YAAY,YAAY,MAAM,WAAW;AAC9E;;;ACnBA,IAAMC,QAAO;AACb,IAAMC,eAAc;AAGb,SAAS,qBAAqB,OAAuE;AAC1G,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,SAAS,MAAM;AACrB,MAAI,UAAU,CAACD,MAAK,KAAK,OAAO,QAAQ,GAAG;AACzC,UAAM,IAAI,MAAM,2EAA2E;AAAA,EAC7F;AACA,QAAM,aAAa,QAAQ,YAAY,KAAK,KAAK;AACjD,MAAI,UAAU,CAACC,aAAY,KAAK,UAAU,GAAG;AAC3C,UAAM,IAAI,MAAM,+EAA+E;AAAA,EACjG;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,gBAAgB,MAAM,mBAAmB;AAAA,IACzC,QAAQ,SAAS,EAAE,UAAU,OAAO,UAAU,WAAW,IAAI;AAAA,EAC/D;AACF;;;AnBCA,IAAMC,QAAO;AAEb,SAAS,cAAc,GAA0C;AAC/D,SACE,CAAC,CAAC,KACF,OAAO,MAAM,YACb,aAAa,KACb,OAAQ,EAA4B,YAAY;AAEpD;AAQO,SAAS,cAAc,QAAgC;AAC5D,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,OAAM,IAAI,MAAM,4CAA4C;AACvG,QAAM,EAAE,IAAAC,KAAI,KAAK,IAAI;AACrB,MAAI,OAAOA,QAAO,YAAY,CAACD,MAAK,KAAKC,GAAE,GAAG;AAC5C,UAAM,IAAI,MAAM,gFAA2E,KAAK,UAAUA,GAAE,CAAC,EAAE;AAAA,EACjH;AACA,MAAI,OAAO,SAAS,YAAY,KAAK,KAAK,MAAM,GAAI,OAAM,IAAI,MAAM,kDAAkD;AAEtH,QAAM,OAAoB,OAAO,QAAQ;AACzC,MAAI,SAAS,aAAa,SAAS,MAAO,OAAM,IAAI,MAAM,6DAAwD,KAAK,UAAU,OAAO,IAAI,CAAC,EAAE;AAE/I,QAAM,MAAW,cAAc,OAAO,GAAG,IAAI,OAAO,MAAM,UAAU,OAAO,OAAO,WAAW,IAAI,CAAC;AAElG,MAAI,SAAS,WAAW;AACtB,QAAI,CAAC,OAAO,UAAU,OAAO,OAAO,OAAO,sBAAsB,YAAY,OAAO,OAAO,sBAAsB,IAAI;AACnH,YAAM,IAAI,MAAM,kEAAkE;AAAA,IACpF;AACA,QAAI,CAAC,OAAO,UAAU,OAAO,OAAO,OAAO,kBAAkB,UAAU;AACrE,YAAM,IAAI,MAAM,8DAA8D;AAAA,IAChF;AACA,QAAI,OAAO,YAAY,QAAW;AAChC,YAAM,IAAI,MAAM,kGAAkG;AAAA,IACpH;AAAA,EACF;AAEA,QAAM,OAAO,YAAY,MAAM,OAAO,IAAI;AAC1C,QAAM,WAAW,gBAAgB,OAAO,QAAQ;AAChD,QAAM,cAAc,mBAAmB,OAAO,WAAW;AACzD,QAAM,QAAQ,EAAE,GAAG,OAAO,OAAO,UAAU,OAAO,OAAO,YAAY,KAAK;AAC1E,QAAM,OAAO,mBAAmB,OAAO,IAAI;AAC3C,QAAM,UAAU,eAAe,QAAQ,GAAG;AAC1C,QAAM,gBAAgB,qBAAqB,OAAO,aAAa;AAC/D,QAAM,gBAAgB,qBAAqB,OAAO,aAAa;AAC/D,QAAM,YAAY,uBAAuB,OAAO,WAAW,GAAG;AAC9D,MAAI,iBAAiB,SAAS,WAAW;AACvC,UAAM,IAAI,MAAM,qFAAqF;AAAA,EACvG;AACA,MAAI,iBAAiB,SAAS,WAAW;AACvC,UAAM,IAAI,MAAM,+EAA+E;AAAA,EACjG;AACA,QAAM,EAAE,QAAQ,MAAM,IAAI;AAAA,IACxB;AAAA,IAAM;AAAA,IAAM,QAAQ,QAAQ,SAAS;AAAA,IAAG;AAAA,IAAa,QAAQ,aAAa;AAAA,IAAG,QAAQ,aAAa;AAAA,EACpG;AACA,QAAM,WAAW,OAAO,YAAY,CAAC,MAAM,YAAY,MAAM;AAG7D,QAAM,UAAU,OAAO,WAAW;AAClC,MAAI,YAAY,YAAY,YAAY,YAAY,YAAY,QAAQ;AACtE,UAAM,IAAI,MAAM,4EAAuE,OAAO,OAAO,CAAC,GAAG;AAAA,EAC3G;AAKA,MAAI,YAAY,UAAU,SAAS,GAAG;AACpC,QAAI,eAAgC;AACpC,QAAI;AACF,qBAAe,OAAO,KAAK,IAAI,KAAK,QAAQ,EAAE,UAAU,CAAC,CAAC;AAAA,IAC5D,QAAQ;AAAA,IAER;AACA,UAAM,UAAU,eAAe,YAAY,UAAU,OAAO,CAAC,MAAM,CAAC,aAAa,SAAS,CAAC,CAAC,IAAI,CAAC;AACjG,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,IAAI;AAAA,QACR,wCAAwC,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,qDAC/D,cAAc,KAAK,IAAI,CAAC;AAAA,MAE1C;AAAA,IACF;AAAA,EACF;AACA,QAAM,oBAAoB,OAAO,OAAO,qBAAqB;AAC7D,MAAI,sBAAsB,YAAY,sBAAsB,aAAa,sBAAsB,SAAS;AACtG,UAAM,IAAI;AAAA,MACR,8FAAyF,OAAO,iBAAiB,CAAC;AAAA,IACpH;AAAA,EACF;AACA,QAAM,QAAQ,EAAE,kBAAkB;AAKlC,QAAM,eAAe,OAAO,YAAY,aAAa,CAAC;AAGtD,QAAM,aAAa,KAAK,OAAO,KAAK,OAAO,SAAS,CAAC,KAAK,KAAK;AAC/D,QAAM,YAAY,aAAa,cAAc,SAAY,aAAa,aAAa;AACnF,MAAI,cAAc,SAAS,CAAC,KAAK,OAAO,SAAS,SAAS,GAAG;AAC3D,UAAM,IAAI;AAAA,MACR,kDAAkD,OAAO,SAAS,CAAC,gCAAgC,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,IAC3H;AAAA,EACF;AACA,QAAM,YAAY,OAAO,YAAY,UAAU,CAAC;AAChD,MAAI,UAAU,gBAAgB,QAAW;AACvC,UAAM,UAAU,UAAU,YAAY,OAAO,CAAC,MAAM,CAAC,SAAS,OAAO,SAAS,CAAC,CAAC;AAChF,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,IAAI;AAAA,QACR,gDAAgD,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,CAAC,yBAAyB,SAAS,OAAO,KAAK,IAAI,CAAC;AAAA,MAC5I;AAAA,IACF;AAAA,EACF;AACA,QAAM,aAAiC;AAAA,IACrC,WAAW,EAAE,WAAW,MAAM,aAAa,SAAS,SAAY,qBAAqB,aAAa,KAAK;AAAA,IACvG,QAAQ,EAAE,aAAa,UAAU,eAAe,MAAM,oBAAoB,UAAU,sBAAsB,KAAK;AAAA,EACjH;AAEA,QAAM,UAAmB;AAAA,IACvB;AAAA,IACA,IAAAA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW,MAAO,SAAS,YAAY,eAAe,MAAM,IAAI;AAAA,EAClE;AACA,MAAI,OAAO,QAAQ,OAAW,SAAQ,MAAM,OAAO;AACnD,SAAO;AACT;;;AoBtKA,SAAS,yBAAuD;AAoBzD,SAAS,gBAAgB,UAA4B,CAAC,GAAc;AACzE,QAAM,OAAO,QAAQ,QAAQ,WAAW,KAAK;AAC7C,QAAM,iBAA0B;AAAA,IAC9B,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW;AAAA,IACX,WAAW;AAAA,IACX,QAAQ;AAAA,MACN,MAAM,EAAE,MAAM,UAAU,OAAO,QAAQ,UAAU,KAAK;AAAA,MACtD,MAAM,EAAE,MAAM,UAAU,OAAO,QAAQ,MAAM,KAAK;AAAA,MAClD,QAAQ,EAAE,MAAM,UAAU,OAAO,UAAU,MAAM,KAAK;AAAA,MACtD,KAAK,EAAE,MAAM,OAAO,OAAO,UAAU;AAAA,MACrC,QAAQ,EAAE,MAAM,UAAU,OAAO,oBAAoB;AAAA,MACrD,YAAY,EAAE,MAAM,QAAQ,OAAO,eAAe,MAAM,KAAK;AAAA,MAC7D,OAAO,EAAE,MAAM,UAAU,OAAO,QAAQ;AAAA,IAC1C;AAAA,IACA,UAAU;AAAA,MACR,QAAQ;AAAA,QACN,EAAE,IAAI,YAAY,OAAO,WAAW;AAAA,QACpC,EAAE,IAAI,WAAW,OAAO,UAAU;AAAA,QAClC,EAAE,IAAI,UAAU,OAAO,SAAS;AAAA,QAChC,EAAE,IAAI,UAAU,OAAO,SAAS;AAAA,QAChC,EAAE,IAAI,UAAU,OAAO,UAAU,UAAU,KAAK;AAAA,MAClD;AAAA,MACA,aAAa;AAAA,QACX,UAAU,CAAC,WAAW,QAAQ;AAAA,QAC9B,SAAS,CAAC,UAAU,UAAU,QAAQ;AAAA,QACtC,QAAQ,CAAC,UAAU,QAAQ;AAAA,QAC3B,QAAQ,CAAC,WAAW,UAAU,QAAQ;AAAA,MACxC;AAAA,IACF;AAAA,IACA,QAAQ,EAAE,MAAM,SAAS;AAAA,EAC3B;AACA,QAAM,kBAAkB,QAAQ,WAAW,CAAC;AAC5C,QAAM,cAAuB;AAAA,IAC3B,GAAG;AAAA,IACH,GAAG;AAAA,IACH,QAAQ;AAAA,MACN,GAAG,eAAe;AAAA,MAClB,GAAI,gBAAgB,UAAU,CAAC;AAAA;AAAA;AAAA,MAG/B,MAAM;AAAA,QACJ,GAAG,eAAe,OAAO;AAAA,QACzB,GAAI,gBAAgB,QAAQ,QAAQ,CAAC;AAAA,QACrC,MAAM;AAAA,QACN,UAAU;AAAA,MACZ;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN,GAAG,eAAe;AAAA,MAClB,GAAI,gBAAgB,UAAU,CAAC;AAAA,IACjC;AAAA,EACF;AACA,QAAM,YAAuB;AAAA,IAC3B,OAAO;AAAA,MACL,SAAS;AAAA,MACT,qBAAqB;AAAA,QACnB,OAAO;AAAA,QACP,aAAa;AAAA,QACb,WAAW;AAAA,QACX,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,QAAQ;AAAA,UACN,MAAM,EAAE,MAAM,UAAU,OAAO,kBAAkB,UAAU,KAAK;AAAA,UAChE,OAAO,EAAE,MAAM,SAAS,OAAO,SAAS,UAAU,KAAK;AAAA,UACvD,UAAU,EAAE,MAAM,UAAU,OAAO,YAAY,UAAU,MAAM,MAAM,KAAK;AAAA,UAC1E,iBAAiB,EAAE,MAAM,UAAU,OAAO,oBAAoB,MAAM,KAAK;AAAA,UACzE,QAAQ,EAAE,MAAM,UAAU,OAAO,mBAAmB,UAAU,KAAK;AAAA,UACnE,YAAY,EAAE,MAAM,UAAU,OAAO,sBAAsB;AAAA,UAC3D,eAAe,EAAE,MAAM,QAAQ,OAAO,gBAAgB;AAAA,UACtD,OAAO,EAAE,MAAM,UAAU,OAAO,iBAAiB;AAAA,QACnD;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,YACN,EAAE,IAAI,aAAa,OAAO,YAAY;AAAA,YACtC,EAAE,IAAI,aAAa,OAAO,YAAY;AAAA,YACtC,EAAE,IAAI,gBAAgB,OAAO,eAAe;AAAA,YAC5C,EAAE,IAAI,YAAY,OAAO,WAAW;AAAA,YACpC,EAAE,IAAI,WAAW,OAAO,UAAU;AAAA,YAClC,EAAE,IAAI,YAAY,OAAO,YAAY,UAAU,KAAK;AAAA,UACtD;AAAA,UACA,aAAa;AAAA,YACX,WAAW,CAAC,aAAa,UAAU;AAAA,YACnC,WAAW,CAAC,gBAAgB,YAAY,UAAU;AAAA,YAClD,cAAc,CAAC,YAAY,UAAU;AAAA,YACrC,UAAU,CAAC,WAAW,UAAU;AAAA,UAClC;AAAA,QACF;AAAA,QACA,QAAQ,EAAE,OAAO,MAAM,MAAM,SAAS;AAAA,MACxC;AAAA,MACA,MAAM;AAAA,QACJ,OAAO;AAAA,QACP,aAAa;AAAA,QACb,WAAW;AAAA,QACX,WAAW;AAAA,QACX,QAAQ;AAAA,UACN,MAAM,EAAE,MAAM,UAAU,OAAO,mBAAmB,UAAU,KAAK;AAAA,UACjE,SAAS,EAAE,MAAM,UAAU,OAAO,kBAAkB,MAAM,KAAK;AAAA,UAC/D,QAAQ,EAAE,MAAM,UAAU,OAAO,UAAU,MAAM,KAAK;AAAA,UACtD,QAAQ,EAAE,MAAM,UAAU,OAAO,UAAU,MAAM,KAAK;AAAA,UACtD,SAAS,EAAE,MAAM,OAAO,OAAO,UAAU;AAAA,UACzC,QAAQ,EAAE,MAAM,UAAU,OAAO,iBAAiB,MAAM,KAAK;AAAA,UAC7D,OAAO,EAAE,MAAM,UAAU,OAAO,QAAQ;AAAA,QAC1C;AAAA,QACA,UAAU;AAAA,UACR,QAAQ;AAAA,YACN,EAAE,IAAI,WAAW,OAAO,UAAU;AAAA,YAClC,EAAE,IAAI,aAAa,OAAO,YAAY;AAAA,YACtC,EAAE,IAAI,aAAa,OAAO,YAAY;AAAA,YACtC,EAAE,IAAI,aAAa,OAAO,YAAY;AAAA,YACtC,EAAE,IAAI,WAAW,OAAO,UAAU;AAAA,YAClC,EAAE,IAAI,YAAY,OAAO,YAAY,UAAU,KAAK;AAAA,YACpD,EAAE,IAAI,UAAU,OAAO,UAAU,UAAU,KAAK;AAAA,UAClD;AAAA,UACA,aAAa;AAAA,YACX,SAAS,CAAC,aAAa,QAAQ;AAAA,YAC/B,WAAW,CAAC,aAAa,aAAa,QAAQ;AAAA,YAC9C,WAAW,CAAC,aAAa,WAAW,QAAQ;AAAA,YAC5C,WAAW,CAAC,WAAW,QAAQ;AAAA,YAC/B,SAAS,CAAC,YAAY,QAAQ;AAAA,YAC9B,QAAQ,CAAC,SAAS;AAAA,UACpB;AAAA,QACF;AAAA,QACA,QAAQ,EAAE,MAAM,SAAS;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,WAAW;AAAA,MACT,kBAAkB;AAAA,QAChB,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,cAAc;AAAA,MAChB;AAAA,MACA,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AACA,MAAI,KAAK,MAAM,SAAS;AACtB,cAAU,UAAW,eAAe;AAAA,MAClC,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,cAAc;AAAA,IAChB;AAAA,EACF;AACA,MAAI,KAAK,MAAM,QAAQ;AACrB,cAAU,UAAW,sBAAsB;AAAA,MACzC,MAAM;AAAA,MACN,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,cAAc;AAAA,IAChB;AAAA,EACF;AACA,SAAO,kBAAkB,MAAM,SAAS;AAC1C;;;ACjLA,SAAS,4BAA4B;;;AC0C9B,SAAS,eACd,SACA,aAA2C,CAAC,GAC5C,MAAM,GAC0B;AAChC,SAAO,WAAW,IAAI,CAAC,MAAM,WAAW;AAAA,IACtC,IAAI,KAAK;AAAA,IACT;AAAA,IACA,MAAM,KAAK;AAAA,IACX,YAAY,KAAK;AAAA,IACjB,GAAI,KAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,IAAI,CAAC;AAAA,IAClE,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,IAC1C,WAAW,KAAK,aAAa;AAAA,IAC7B,QAAQ,KAAK,WAAW;AAAA,IACxB,WAAW;AAAA,EACb,EAAE;AACJ;AAqBO,SAAS,WACd,MACS;AACT,SAAO,EAAE,KAAK,aAAa,MAAM,CAAC,KAAK;AACzC;AAUO,SAAS,YACd,MACA,OACA,cACS;AACT,MAAI,WAAW,IAAI,EAAG,QAAO;AAC7B,SAAO,QAAQ,MAAM,wBAAwB,KAAK,iBAAiB,YAAY;AACjF;AAGA,SAAS,QAAQ,GAAgB,GAAwB;AACvD,SAAO,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,cAAc,EAAE,EAAE;AAC7D;AAWO,SAAS,aAAa,OAAkBC,QAA+B,CAAC,GAAkB;AAC/F,QAAM,SAASA,MAAK,OAAO,CAAC,SAAS,KAAK,MAAM;AAChD,MAAI,OAAO,OAAQ,QAAO,CAAC,GAAG,MAAM,EAAE,KAAK,OAAO;AAClD,SAAO,CAAC;AAAA,IACN,IAAI;AAAA,IACJ,SAAS,OAAO,MAAM,MAAM,EAAE;AAAA,IAC9B,MAAM;AAAA,IACN,YAAY,MAAM,sBAAsB;AAAA,IACxC,GAAI,MAAM,gBAAgB,EAAE,eAAe,MAAM,cAAc,IAAI,CAAC;AAAA,IACpE,WAAW;AAAA,IACX,QAAQ;AAAA,EACV,CAAC;AACH;AAGO,SAAS,eACdC,QACA,OACA,cACe;AACf,SAAOA,OAAM,OAAO,CAAC,SAAS,KAAK,UAAU,YAAY,MAAM,OAAO,YAAY,CAAC;AACrF;AASO,SAAS,SACdA,QACA,QACoB;AACpB,MAAI,CAAC,OAAQ,QAAOA,OAAM,WAAW,IAAIA,OAAM,CAAC,IAAK;AACrD,SAAOA,OAAM,KAAK,CAAC,SAAS,KAAK,OAAO,MAAM,KAAK;AACrD;AAYO,SAAS,gBAAgBA,QAAiD;AAC/E,SAAOA,OAAM,IAAI,CAAC,UAAU;AAAA,IAC1B,IAAI,KAAK;AAAA,IACT,MAAM,KAAK;AAAA,IACX,YAAY,KAAK;AAAA,IACjB,OAAO,KAAK,SAAS;AAAA,IACrB,MAAM,WAAW,IAAI;AAAA,EACvB,EAAE;AACJ;;;AD1HO,SAAS,yBACd,SACA,UAAqC,CAAC,GACR;AAC9B,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,MAAM,QAAQ,OAAO,KAAK,IAAI;AACpC,QAAM,SAAS,QAAQ,OAAO;AAE9B,QAAM,UAAU,qBAAqB,QAAQ,KAAK;AAAA,IAChD;AAAA,IACA;AAAA,IACA,GAAI,QAAQ,oBAAoB,EAAE,mBAAmB,OAAO,kBAAkB,IAAI,CAAC;AAAA,IACnF,GAAI,QAAQ,UAAU,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;AAAA,IACrD,GAAI,QAAQ,aAAa,EAAE,YAAY,OAAO,WAAW,IAAI,CAAC;AAAA,EAChE,CAAC;AAED,QAAM,QAA2B,CAAC,GAAI,QAAQ,SAAS,CAAC,CAAE;AAC1D,QAAM,QAAQ,QAAQ,UAAU;AAChC,MAAI,OAAO;AACT,UAAM,KAAK,EAAE,IAAI,SAAS,IAAI,UAAU,KAAK,EAAE,MAAM,MAAM,OAAO,QAAQ,GAAG,GAAG,OAAO,EAAE,GAAG,OAAO,WAAW,IAAI,EAAE,CAAC;AAIrH,eAAW,QAAQ,eAAe,QAAQ,IAAI,QAAQ,OAAO,OAAO,GAAG,GAAG;AACxE,YAAM,KAAK;AAAA,QACT,IAAI,QAAQ,OAAO,KAAK,EAAE,CAAC;AAAA,QAC3B,IAAI;AAAA,QACJ,KAAK,EAAE,MAAM,MAAM,OAAO,OAAO,KAAK,EAAE,EAAE;AAAA,QAC1C,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAIA,QAAM,YAAY,QAAQ,OAAO,SAAS,SAAS,UAAU,KAAK;AAClE,QAAM,WAAgC,WAClC;AAAA,IACE,MAAM;AAAA,IACN,OAAO,CAAC,kBAAkB,mBAAmB,KAAK;AAAA,IAClD,UACE,GAAG,QAAQ,IAAI;AAAA,EAEnB,IACA;AAAA,IACE,MAAM;AAAA,IACN,OAAO,CAAC,oBAAoB,iBAAiB;AAAA,IAC7C,UACE,GAAG,QAAQ,IAAI;AAAA,EAEnB;AAEJ,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO,YAAY,QAAQ,IAAI;AAAA,IAC/B,KAAK;AAAA,IACL,QAAQ;AAAA,MACN,UAAU,EAAE,GAAG,QAAQ,OAAO,UAAU,GAAG,QAAQ,OAAO,SAAS;AAAA,MACnE,OAAO,EAAE,GAAG,QAAQ,OAAO,OAAO,GAAG,QAAQ,OAAO,MAAM;AAAA,IAC5D;AAAA,IACA,OAAO,EAAE,GAAG,QAAQ,OAAO,GAAG,QAAQ,MAAM;AAAA,IAC5C;AAAA,IACA,QAAQ;AAAA,MACN,GAAI,QAAQ,UAAU,CAAC;AAAA;AAAA;AAAA,MAGvB,EAAE,MAAM,yBAAyB,gBAAgB,IAAI;AAAA,MACrD,GAAI,QAAQ,QAAQ,QAAQ,SAAS,IACjC,CAAC,EAAE,MAAM,wBAAwB,gBAAgB,IAAI,CAAC,IACtD,CAAC;AAAA,MACL,GAAI,QAAQ,QAAQ,QAAQ,KAAK,CAAC,WAAW,OAAO,YAAY,SAAS,CAAC,IACtE,CAAC;AAAA,QACC,MAAM;AAAA,QACN,gBAAgB;AAAA,MAClB,CAAC,IACD,CAAC;AAAA;AAAA;AAAA,MAGL,GAAI,QAAQ,UAAU,UAClB,CAAC,EAAE,MAAM,yBAAyB,gBAAgB,IAAI,CAAC,IACvD,CAAC;AAAA,MACL,GAAI,QAAQ,gBACR;AAAA,QACE,EAAE,MAAM,uBAAuB,gBAAgB,IAAI;AAAA,QACnD,EAAE,MAAM,6BAA6B,gBAAgB,IAAI;AAAA,MAC3D,IACA,CAAC;AAAA,IACP;AAAA,IACA;AAAA,EACF;AACF;;;AE/IO,IAAM,KAAK;AACX,IAAMC,QAAO;AACb,IAAM,YAAY,oBAAI,IAAI,CAAC,iBAAiB,YAAY,eAAe,UAAU,UAAU,SAAS,iBAAiB,CAAC;AACtH,IAAM,cAAc,oBAAI,IAAI,CAAC,QAAQ,OAAO,CAAC;AAC7C,IAAM,cAAc,oBAAI,IAAI,CAAC,aAAa,aAAa,CAAC;AACxD,IAAM,YAAY,oBAAI,IAAI,CAAC,MAAM,QAAQ,SAAS,WAAW,cAAc,YAAY,kBAAkB,gBAAgB,QAAQ,CAAC;AAClI,IAAM,WAAW,oBAAI,IAAI,CAAC,WAAW,SAAS,UAAU,CAAC;AACzD,IAAM,gBAAgB,oBAAI,IAAI,CAAC,QAAQ,SAAS,CAAC;AACjD,IAAM,cAAc,oBAAI,IAAI,CAAC,SAAS,OAAO,CAAC;AAC9C,IAAM,aAAa,oBAAI,IAAI,CAAC,UAAU,SAAS,gBAAgB,UAAU,CAAC;AAC1E,IAAM,gBAAgB,oBAAI,IAAI,CAAC,UAAU,OAAO,CAAC;AACjD,IAAM,YAAY;AAClB,IAAM,eAAe;AACrB,IAAM,WAAW;AAEjB,IAAM,SAAS,CAAC,UACrB,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC/D,QACA;AAEC,SAAS,YAAY,OAAgCC,UAA8B,MAAc,QAAwB;AAC9H,aAAW,OAAO,OAAO,KAAK,KAAK,EAAG,KAAI,CAACA,SAAQ,IAAI,GAAG,EAAG,QAAO,KAAK,GAAG,IAAI,IAAI,GAAG,mBAAmB;AAC5G;AAEO,SAAS,UAAU,OAAgB,MAAc,QAAkB,MAAM,UAAU,WAAW,OAA2B;AAC9H,MAAI,UAAU,QAAW;AACvB,QAAI,SAAU,QAAO,KAAK,GAAG,IAAI,cAAc;AAC/C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,KAAK,GAAG,IAAI,mBAAmB;AACtC,WAAO;AAAA,EACT;AACA,QAAM,YAAY,MAAM,KAAK;AAC7B,MAAI,YAAY,CAAC,UAAW,QAAO,KAAK,GAAG,IAAI,cAAc;AAC7D,MAAI,UAAU,SAAS,IAAK,QAAO,KAAK,GAAG,IAAI,oBAAoB,IAAI,eAAe,OAAO,CAAC,aAAa;AAC3G,SAAO;AACT;AAEO,SAAS,WACd,OACA,MACA,QACAC,QACA,UACmC;AACnC,QAAM,MAAM,OAAO,KAAK;AACxB,MAAI,CAAC,KAAK;AACR,WAAO,KAAK,GAAG,IAAI,oBAAoB;AACvC,WAAO;AAAA,EACT;AACA,cAAY,KAAK,YAAY,MAAM,MAAM;AACzC,QAAM,SAAS,UAAU,IAAI,QAAQ,GAAG,IAAI,WAAW,QAAQ,IAAI,IAAI,KAAK;AAC5E,MAAI,UAAU,CAAC,GAAG,KAAK,MAAM,EAAG,QAAO,KAAK,GAAG,IAAI,2CAA2C;AAC9F,MAAIA,OAAM,QAAQ,CAACA,OAAM,IAAI,MAAM,EAAG,QAAO,KAAK,GAAG,IAAI,wCAAwC;AACjG,MAAI,UAAU,SAAS,WAAW,UAAU,CAAC,SAAS,QAAQ,SAAS,MAAM,GAAG;AAC9E,WAAO,KAAK,GAAG,IAAI,wCAAwC;AAAA,EAC7D;AACA,QAAM,QAAQ,UAAU,IAAI,OAAO,GAAG,IAAI,UAAU,MAAM;AAC1D,QAAM,eAAe,UAAU,IAAI,cAAc,GAAG,IAAI,iBAAiB,QAAQ,YAAY;AAC7F,QAAM,WAAW,UAAU,IAAI,UAAU,GAAG,IAAI,aAAa,MAAM;AACnE,SAAO;AAAA,IACL;AAAA,IACA,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IACzB,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,EACjC;AACF;;;ACnCO,SAAS,8BACd,OACA,UAA0C,CAAC,GACZ;AAC/B,QAAM,SAAmB,CAAC;AAC1B,QAAM,OAAO,OAAO,KAAK;AACzB,MAAI,CAAC,KAAM,QAAO,EAAE,IAAI,OAAO,QAAQ,CAAC,4BAA4B,EAAE;AACtE,cAAY,MAAM,WAAW,YAAY,MAAM;AAC/C,MAAI,KAAK,kBAAkB,8BAA+B,QAAO,KAAK,kCAAkC;AACxG,MAAI,CAAC,OAAO,UAAU,KAAK,QAAQ,KAAK,OAAO,KAAK,QAAQ,IAAI,EAAG,QAAO,KAAK,8CAA8C;AAC7H,MAAI,CAAC,OAAO,UAAU,KAAK,WAAW,KAAK,OAAO,KAAK,WAAW,IAAI,EAAG,QAAO,KAAK,+DAA+D;AAEpJ,QAAM,YAAY,OAAO,KAAK,MAAM;AACpC,MAAI,SAA8B,EAAE,MAAM,WAAW,OAAO,UAAU;AACtE,MAAI,CAAC,UAAW,QAAO,KAAK,mCAAmC;AAAA,OAC1D;AACH,gBAAY,WAAW,aAAa,mBAAmB,MAAM;AAC7D,UAAM,OAAO,UAAU;AACvB,UAAM,QAAQ,UAAU,UAAU,OAAO,yBAAyB,QAAQ,IAAI,IAAI,KAAK;AACvF,QAAI,SAAS,YAAY,SAAS,UAAW,QAAO,KAAK,gDAAgD;AACzG,QAAI,SAAS,CAAC,GAAG,KAAK,KAAK,EAAG,QAAO,KAAK,oDAAoD;AAC9F,QAAI,QAAQ,cAAc,SAAS,QAAQ,WAAY,QAAO,KAAK,gCAAgC,QAAQ,UAAU,EAAE;AACvH,QAAI,QAAQ,eAAe,UAAU,QAAQ,YAAa,QAAO,KAAK,iCAAiC,QAAQ,WAAW,EAAE;AAC5H,QAAI,SAAS,YAAY,SAAS,UAAW,UAAS,EAAE,MAAM,MAAM;AAAA,EACtE;AAEA,MAAI;AACJ,MAAI,KAAK,WAAW,QAAW;AAC7B,UAAM,YAAY,OAAO,KAAK,MAAM;AACpC,QAAI,CAAC,UAAW,QAAO,KAAK,mCAAmC;AAAA,SAC1D;AACH,kBAAY,WAAW,aAAa,mBAAmB,MAAM;AAC7D,YAAM,YAAY,UAAU,UAAU,WAAW,6BAA6B,QAAQ,IAAI,IAAI,KAAK;AACnG,YAAM,cAAc,UAAU,UAAU,aAAa,+BAA+B,QAAQ,IAAI,IAAI,KAAK;AACzG,eAAS,EAAE,WAAW,YAAY;AAAA,IACpC;AAAA,EACF;AACA,MAAI,OAAO,SAAS,YAAY,CAAC,OAAQ,QAAO,KAAK,gDAAgD;AACrG,MAAI,OAAO,SAAS,aAAa,OAAQ,QAAO,KAAK,sDAAsD;AAE3G,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,EAAG,QAAO,KAAK,iCAAiC;AAC7E,QAAM,WAAW,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC;AAC3D,MAAI,SAAS,SAAS,UAAW,QAAO,KAAK,mCAAmC,SAAS,UAAU;AACnG,QAAM,UAAU,IAAI,KAAK,QAAQ,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AACpE,QAAM,iBAAiB,IAAI,KAAK,QAAQ,eAAe,CAAC,GAAG,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AACjF,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,QAA6B,CAAC;AACpC,aAAW,CAAC,OAAO,KAAK,KAAK,SAAS,MAAM,GAAG,SAAS,EAAE,QAAQ,GAAG;AACnE,UAAM,OAAO,kBAAkB,KAAK;AACpC,UAAM,MAAM,OAAO,KAAK;AACxB,QAAI,CAAC,KAAK;AACR,aAAO,KAAK,GAAG,IAAI,oBAAoB;AACvC;AAAA,IACF;AACA,gBAAY,KAAK,WAAW,MAAM,MAAM;AACxC,UAAMC,MAAK,UAAU,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAI,IAAI,KAAK;AAChE,UAAM,OAAO,UAAU,IAAI,MAAM,GAAG,IAAI,SAAS,QAAQ,KAAK,IAAI,KAAK;AACvE,UAAM,QAAQ,UAAU,IAAI,OAAO,GAAG,IAAI,UAAU,QAAQ,UAAU,IAAI,KAAK;AAC/E,QAAIA,OAAM,CAAC,GAAG,KAAKA,GAAE,EAAG,QAAO,KAAK,GAAG,IAAI,uCAAuC;AAClF,QAAI,QAAQ,CAACC,MAAK,KAAK,IAAI,EAAG,QAAO,KAAK,GAAG,IAAI,oCAAoC;AACrF,QAAI,IAAI,IAAID,GAAE,KAAK,eAAe,IAAIA,GAAE,EAAG,QAAO,KAAK,GAAG,IAAI,wBAAwBA,GAAE,GAAG;AAC3F,QAAI,MAAM,IAAI,IAAI,MAAM,QAAQ,eAAe,CAAC,GAAG,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,EAAG,QAAO,KAAK,GAAG,IAAI,qBAAqB,IAAI,GAAG;AACtI,QAAI,IAAIA,GAAE;AACV,UAAM,IAAI,IAAI;AAEd,UAAM,SAAS,OAAO,IAAI,UAAU;AACpC,QAAI,aAAmC,EAAE,SAAS,WAAW,OAAO,MAAM;AAC1E,QAAI,CAAC,OAAQ,QAAO,KAAK,GAAG,IAAI,+BAA+B;AAAA,SAC1D;AACH,kBAAY,QAAQ,UAAU,GAAG,IAAI,eAAe,MAAM;AAC1D,YAAM,UAAU,UAAU,OAAO,SAAS,GAAG,IAAI,uBAAuB,QAAQ,KAAK,IAAI,KAAK;AAC9F,YAAM,QAAQ,OAAO;AACrB,UAAI,CAAC,OAAO,UAAU,KAAK,KAAK,OAAO,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,KAAW;AAC9E,eAAO,KAAK,GAAG,IAAI,0DAA0D;AAAA,MAC/E;AACA,YAAM,WAAW,UAAU,OAAO,UAAU,GAAG,IAAI,wBAAwB,QAAQ,EAAE;AACrF,mBAAa,EAAE,SAAS,OAAO,OAAO,UAAU,KAAK,IAAI,OAAO,KAAK,IAAI,OAAO,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,EAAG;AAAA,IACpH;AAEA,UAAM,cAAc,OAAO,IAAI,QAAQ;AACvC,QAAI,WAA+B,EAAE,MAAM,cAAc;AACzD,QAAI,CAAC,YAAa,QAAO,KAAK,GAAG,IAAI,6BAA6B;AAAA,SAC7D;AACH,kBAAY,aAAa,eAAe,GAAG,IAAI,aAAa,MAAM;AAClE,UAAI,YAAY,SAAS,eAAe;AACtC,YAAI,YAAY,YAAY,OAAW,QAAO,KAAK,GAAG,IAAI,oDAAoD;AAAA,MAChH,WAAW,YAAY,SAAS,SAAS;AACvC,YAAI,CAAC,MAAM,QAAQ,YAAY,OAAO,KAAK,YAAY,QAAQ,WAAW,GAAG;AAC3E,iBAAO,KAAK,GAAG,IAAI,6CAA6C;AAAA,QAClE;AACA,cAAM,SAAS,MAAM,QAAQ,YAAY,OAAO,IAAI,YAAY,UAAU,CAAC;AAC3E,cAAM,aAAuB,CAAC;AAC9B,mBAAW,CAAC,WAAWE,MAAK,KAAK,OAAO,QAAQ,GAAG;AACjD,gBAAM,OAAO,UAAUA,QAAO,GAAG,IAAI,qBAAqB,SAAS,KAAK,QAAQ,IAAI,IAAI,KAAK;AAC7F,cAAI,WAAW,SAAS,IAAI,EAAG,QAAO,KAAK,GAAG,IAAI,iCAAiC,IAAI,GAAG;AAC1F,cAAI,QAAQ,QAAQ,CAAC,QAAQ,IAAI,IAAI,EAAG,QAAO,KAAK,GAAG,IAAI,iDAAiD,IAAI,GAAG;AACnH,qBAAW,KAAK,IAAI;AAAA,QACtB;AACA,mBAAW,EAAE,MAAM,SAAS,SAAS,WAAW;AAAA,MAClD,MAAO,QAAO,KAAK,GAAG,IAAI,6CAA6C;AAAA,IACzE;AAEA,UAAM,UAAU,UAAU,IAAI,SAAS,GAAG,IAAI,YAAY,QAAQ,GAAK;AACvE,UAAM,iBAAiB,UAAU,IAAI,gBAAgB,GAAG,IAAI,mBAAmB,QAAQ,YAAY;AACnG,UAAM,eAAe,UAAU,IAAI,cAAc,GAAG,IAAI,iBAAiB,QAAQ,cAAc,IAAI,KAAK;AACxG,QAAI;AACJ,QAAI,IAAI,WAAW,QAAW;AAC5B,YAAM,YAAY,OAAO,IAAI,MAAM;AACnC,UAAI,CAAC,UAAW,QAAO,KAAK,GAAG,IAAI,2BAA2B;AAAA,WACzD;AACH,oBAAY,WAAW,aAAa,GAAG,IAAI,WAAW,MAAM;AAC5D,cAAM,QAAQ,UAAU;AACxB,YAAI,UAAU,YAAY,UAAU,UAAW,QAAO,KAAK,GAAG,IAAI,yCAAyC;AAC3G,YAAI,OAAO,SAAS,aAAa,UAAU,SAAU,QAAO,KAAK,GAAG,IAAI,kDAAkD;AAC1H,YAAI,OAAO,SAAS,YAAY,UAAU,YAAY,UAAU,UAAU,OAAW,QAAO,KAAK,GAAG,IAAI,0DAA0D;AAClK,YAAI,OAAO,SAAS,YAAY,UAAU,aAAa,UAAU,UAAU,OAAW,QAAO,KAAK,GAAG,IAAI,2DAA2D;AACpK,cAAM,QAAQ,UAAU,UAAU,SAAY,SAAY,WAAW,UAAU,OAAO,GAAG,IAAI,iBAAiB,QAAQ,SAAS,QAAQ;AACvI,YAAI,UAAU,SAAU,UAAS,EAAE,OAAO,OAAO,SAAS,EAAE,QAAQ,GAAG,EAAE;AAAA,iBAChE,UAAU,UAAW,UAAS,EAAE,OAAO,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAG;AAAA,MAC9E;AAAA,IACF;AACA,UAAM,KAAK,EAAE,IAAAF,KAAI,MAAM,OAAO,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,GAAI,YAAY,UAAU,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC,GAAI,cAAc,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAAA,EACnL;AAEA,QAAM,SAAS,oBAAI,IAAI,CAAC,GAAG,gBAAgB,GAAG,GAAG,CAAC;AAClD,aAAW,CAAC,OAAO,IAAI,KAAK,MAAM,QAAQ,GAAG;AAC3C,UAAM,WAAW,KAAK,WAAW;AACjC,QAAI,YAAY,CAAC,OAAO,IAAI,QAAQ,EAAG,QAAO,KAAK,kBAAkB,KAAK,kDAAkD,QAAQ,GAAG;AACvI,QAAI,aAAa,KAAK,GAAI,QAAO,KAAK,kBAAkB,KAAK,+CAA+C;AAAA,EAC9G;AACA,aAAW,QAAQ,OAAO;AACxB,UAAM,OAAO,oBAAI,IAAI,CAAC,KAAK,EAAE,CAAC;AAC9B,QAAI,WAAW,KAAK,WAAW;AAC/B,WAAO,UAAU;AACf,UAAI,KAAK,IAAI,QAAQ,GAAG;AACtB,eAAO,KAAK,kDAAkD,KAAK,EAAE,GAAG;AACxE;AAAA,MACF;AACA,WAAK,IAAI,QAAQ;AACjB,iBAAW,MAAM,KAAK,CAAC,cAAc,UAAU,OAAO,QAAQ,GAAG,WAAW;AAAA,IAC9E;AAAA,EACF;AAEA,MAAI;AACJ,MAAI,KAAK,oBAAoB,QAAW;AACtC,QAAI,OAAO,SAAS,UAAW,QAAO,KAAK,gEAAgE;AAC3G,QAAI,CAAC,MAAM,QAAQ,KAAK,eAAe,EAAG,QAAO,KAAK,2CAA2C;AACjG,UAAM,SAAS,MAAM,QAAQ,KAAK,eAAe,IAAI,KAAK,kBAAkB,CAAC;AAC7E,UAAM,OAAO,oBAAI,IAAY;AAC7B,sBAAkB,CAAC;AACnB,eAAW,CAAC,OAAO,KAAK,KAAK,OAAO,QAAQ,GAAG;AAC7C,YAAM,OAAO,4BAA4B,KAAK;AAC9C,YAAM,MAAM,OAAO,KAAK;AACxB,UAAI,CAAC,KAAK;AACR,eAAO,KAAK,GAAG,IAAI,oBAAoB;AACvC;AAAA,MACF;AACA,kBAAY,KAAK,eAAe,MAAM,MAAM;AAC5C,YAAM,SAAS,UAAU,IAAI,QAAQ,GAAG,IAAI,WAAW,QAAQ,IAAI,IAAI,KAAK;AAC5E,UAAI,KAAK,IAAI,MAAM,EAAG,QAAO,KAAK,GAAG,IAAI,uBAAuB,MAAM,GAAG;AACzE,WAAK,IAAI,MAAM;AACf,YAAM,cAAc,QAAQ,eAAe,CAAC,GAAG,KAAK,CAAC,SAAS,KAAK,OAAO,MAAM;AAChF,UAAI,CAAC,WAAY,QAAO,KAAK,GAAG,IAAI,sCAAsC;AAAA,eACjE,WAAW,QAAQ,UAAU,UAAW,QAAO,KAAK,GAAG,IAAI,2DAA2D;AAC/H,YAAM,QAAQ,WAAW,IAAI,OAAO,GAAG,IAAI,UAAU,QAAQ,SAAS,YAAY,QAAQ;AAC1F,UAAI,MAAO,iBAAgB,KAAK,EAAE,QAAQ,MAAM,CAAC;AAAA,IACnD;AAAA,EACF;AACA,MAAI,OAAO,OAAQ,QAAO,EAAE,IAAI,OAAO,OAAO;AAC9C,SAAO,EAAE,IAAI,MAAM,OAAO;AAAA,IACxB,eAAe;AAAA,IACf,UAAU,OAAO,KAAK,QAAQ;AAAA,IAC9B,aAAa,OAAO,KAAK,WAAW;AAAA,IACpC;AAAA,IACA,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B;AAAA,IACA,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,EAC/C,EAAE;AACJ;AAGO,SAAS,sBAAsB,OAAgB,UAA0C,CAAC,GAA0B;AACzH,QAAM,SAAS,8BAA8B,OAAO,OAAO;AAC3D,MAAI,CAAC,OAAO,GAAI,OAAM,IAAI,UAAU,oCAAoC,OAAO,OAAO,KAAK,IAAI,CAAC,EAAE;AAClG,SAAO,OAAO;AAChB;;;AC3NO,IAAM,gCAAgC;AAEtC,IAAM,sBAAsB;AAE5B,IAAM,8BAA8B;AAgJ3C,IAAM,YAAY,CAAC,GAA+B,MAChD,EAAE,WAAW,QAAQ,cAAc,EAAE,WAAW,OAAO,KACpD,EAAE,WAAW,QAAQ,EAAE,WAAW,SAClC,EAAE,MAAM,cAAc,EAAE,KAAK,KAC7B,EAAE,GAAG,cAAc,EAAE,EAAE;AAGrB,SAAS,qBACd,QACA,SACwB;AACxB,QAAM,QAAsC,CAAC;AAC7C,QAAM,cAAc,oBAAI,IAAwC;AAChE,aAAW,QAAQ,QAAQ,SAAS,CAAC,GAAG;AACtC,UAAM,YAAY,EAAE,GAAG,MAAM,QAAQ,OAAQ,OAAO;AACpD,gBAAY,IAAI,KAAK,IAAI,SAAS;AAClC,UAAM,KAAK,SAAS;AAAA,EACtB;AACA,aAAW,YAAY,SAAS,mBAAmB,CAAC,GAAG;AACrD,UAAM,OAAO,YAAY,IAAI,SAAS,MAAM;AAC5C,QAAI,MAAM,QAAQ,UAAU,UAAW,MAAK,SAAS,EAAE,OAAO,WAAW,OAAO,SAAS,MAAM;AAAA,EACjG;AACA,aAAW,QAAQ,SAAS,SAAS,CAAC,GAAG;AACvC,QAAI,YAAY,IAAI,KAAK,EAAE,KAAK,MAAM,KAAK,CAAC,cAAc,UAAU,SAAS,KAAK,IAAI,GAAG;AACvF,YAAM,IAAI,UAAU,wBAAwB,KAAK,EAAE,iCAAiC;AAAA,IACtF;AACA,UAAM,KAAK,EAAE,GAAG,MAAM,QAAQ,QAAS,OAAO,CAAC;AAAA,EACjD;AACA,SAAO;AAAA,IACL,OAAO,MAAM,KAAK,SAAS;AAAA,IAC3B,gBAAgB,QAAQ,YAAY;AAAA,IACpC,iBAAiB,SAAS,YAAY;AAAA,EACxC;AACF;AAEA,IAAM,UAAU,CAAC,MAAyB,WACxC,OAAO,SACJ,KAAK,SAAS,SAAS,iBACtB,OAAO,WAAW,QAAQ,KAAK,SAAS,QAAQ,SAAS,OAAO,MAAM;AAGrE,SAAS,qBACd,SACA,QACAG,QACyB;AACzB,QAAM,YAAY,IAAI,IAAIA,OAAM,OAAO,CAAC,SAAS,KAAK,WAAW,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AACtG,SAAO;AAAA,IACL,QAAQ,EAAE,GAAG,OAAO;AAAA,IACpB,WAAW,EAAE,QAAQ,QAAQ,gBAAgB,SAAS,QAAQ,gBAAgB;AAAA,IAC9E,OAAO,QAAQ,MAAM,IAAI,CAAC,SAAS;AACjC,YAAM,UAAU,QAAQ,MAAM,MAAM;AACpC,YAAM,QAAQ,CAAC,UAAU,KAAK,QAAQ,QAAQ;AAC9C,YAAM,OAAO,QAAQ,UAAU,IAAI,MAAM,MAAM,IAAI;AACnD,YAAM,SAAS,SAAS,QAAQ,OAAO,KAAK,SAAS,YAAY,OAAO,KAAK,eAAe,WACxF,EAAE,GAAG,OAAO,UAAU,KAAK,MAAM,YAAY,KAAK,WAAW,IAC7D;AACJ,aAAO;AAAA,QACL,IAAI,KAAK;AAAA,QACT,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ,GAAI,KAAK,UAAU,EAAE,SAAS,KAAK,QAAQ,IAAI,CAAC;AAAA,QAChD,YAAY,KAAK;AAAA,QACjB,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,QAAQ,UAAU,YAAqB;AAAA,QACvC,GAAI,KAAK,iBAAiB,EAAE,gBAAgB,KAAK,eAAe,IAAI,CAAC;AAAA,QACrE,GAAI,UAAU,EAAE,cAAc,KAAK,aAAa,IAAI,CAAC;AAAA,QACrD,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC7NA,IAAM,UAAU,IAAI,YAAY;AAEhC,SAAS,eAAe,OAAwB;AAC9C,MAAI,UAAU,QAAQ,OAAO,UAAU,aAAa,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAC1G,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AACA,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,IAAI,MAAM,IAAI,cAAc,EAAE,KAAK,GAAG,CAAC;AACxE,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,UAAU,8CAA8C;AACjG,QAAMC,UAAS;AACf,QAAM,UAAU,OAAO,KAAKA,OAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ;AAC1D,UAAM,OAAOA,QAAO,GAAG;AACvB,WAAO,SAAS,SAAY,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,eAAe,IAAI,CAAC,EAAE;AAAA,EACpF,CAAC;AACD,SAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9B;AAGO,SAAS,uBAAuB,OAAwB;AAC7D,SAAO,eAAe,KAAK;AAC7B;AAGA,eAAsB,oBAAoB,UAAoC;AAC5E,QAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAW,QAAQ,OAAO,uBAAuB,QAAQ,CAAC,CAAC;AACrG,SAAO,UAAU,MAAM,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AAC5G;AAGA,eAAsB,4BAA4B,UAA4D;AAC5G,SAAO,EAAE,UAAU,QAAQ,MAAM,oBAAoB,QAAQ,EAAE;AACjE;;;ACIO,SAAS,OAAO,UAAkB,MAAsC;AAC7E,SAAO,SAAS,QAAQ,kBAAkB,CAAC,GAAG,QAAgB,KAAK,GAAG,KAAK,EAAE;AAC/E;AAGA,SAAS,UAAU,OAAmB,MAAsD;AAC1F,SAAO;AAAA,IACL,GAAG;AAAA,IACH,kBAAkB,MAAM,oBAAoB;AAAA,IAC5C,gBAAgB,MAAM,kBAAkB;AAAA,IACxC,WAAW,MAAM,aAAa;AAAA,EAChC;AACF;AASO,SAAS,mBAAmB,OAAmB,UAAkB,MAA6C;AACnH,QAAM,MAAM,MAAM,iBAAiB,QAAQ;AAC3C,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,OAAO,IAAI,MAAM,UAAU,OAAO,IAAI,CAAC;AAChD;AASO,SAAS,cAAc,WAAwD;AACpF,SAAO,UAAU,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK;AAC3C;AA2BO,SAAS,aAAa,OAUR;AACnB,QAAM,MAAM,MAAM,MAAM,iBAAiB,MAAM,QAAQ;AACvD,MAAI,CAAC,IAAK,QAAO,EAAE,SAAS,OAAO,QAAQ,mBAAmB;AAC9D,MAAI,IAAI,YAAY,SAAS,CAAC,MAAM,MAAO,QAAO,EAAE,SAAS,OAAO,QAAQ,WAAW;AAEvF,QAAM,OAAO,UAAU,MAAM,OAAO,MAAM,IAAI;AAC9C,QAAM,SAAS,MAAM,YAAY;AACjC,QAAM,WAAW,CAAC,UAAU,CAAC,CAAC,MAAM,MAAM;AAC1C,QAAM,YACJ,CAAC,UAAU,CAAC,WAAW,aAAa,MAAM,kBAAkB,eAAe;AAC7E,QAAM,KAAK,WAAY,MAAM,MAAM,aAAwB,MAAM;AACjE,QAAM,WAAW,WAAW,WAAW,MAAM,OAAO,IAAI,SAAS,IAAI;AACrE,QAAMC,QAAO,WACT,sCAAsC,MAAM,EAAE;AAAA;AAAA,IAAU,OAAO,IAAI,MAAM,IAAI,IAC7E,OAAO,IAAI,MAAM,IAAI;AACzB,SAAO,EAAE,SAAS,MAAM,WAAW,IAAI,SAAS,MAAAA,OAAM,YAAY,SAAS;AAC7E;;;AC7DA,eAAsB,cAAc,MAAkB,OAA2C;AAC/F,QAAM,EAAE,UAAAC,UAAS,IAAI,MAAM,KAAK,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,MAAM,UAAU,EAAE,EAAE,EAAE,CAAC;AACvG,QAAM,QAAS,MAAM,QAAQA,SAAQ,IAAIA,YAAW,CAAC;AACrD,MAAI,cAAc,KAAK,EAAG,QAAO,EAAE,MAAM,MAAM,QAAQ,eAAe;AAEtE,QAAM,kBAAkB,QAAQ,KAAK,UAAU,KAAK,IAAI;AACxD,QAAM,WAAW,aAAa;AAAA,IAC5B,SAAS,KAAK;AAAA,IACd,OAAO,MAAM;AAAA,IACb,UAAU,MAAM;AAAA,IAChB,IAAI,MAAM;AAAA,IACV,MAAM,MAAM;AAAA,IACZ;AAAA,IACA,OAAO,MAAM;AAAA,EACf,CAAC;AACD,MAAI,CAAC,SAAS,QAAS,QAAO,EAAE,MAAM,OAAO,QAAQ,SAAS,OAAO;AAErE,MAAI;AACJ,MAAI;AACJ,MAAI,SAAS,cAAc,gBAAgB,KAAK,UAAU,KAAK,MAAM;AACnE,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,OAAO,KAAK;AAAA,QACjC,MAAM,KAAK;AAAA,QACX,IAAI,CAAC,SAAS,EAAE;AAAA,QAChB,SAAS,SAAS;AAAA,QAClB,MAAM,SAAS;AAAA,QACf,SAAS,MAAM,MAAM;AAAA,MACvB,CAAC;AACD,kBAAY,IAAI;AAAA,IAClB,SAAS,GAAG;AACV,cAAQ,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC;AAAA,IACnD;AAAA,EACF;AAEA,QAAMC,MAAK,KAAK,MAAM;AACtB,QAAM,MAA+B;AAAA,IACnC,IAAAA;AAAA,IACA,SAAS,MAAM,MAAM;AAAA,IACrB,IAAI,SAAS;AAAA,IACb,UAAU,MAAM;AAAA,IAChB,SAAS,SAAS;AAAA,IAClB,MAAM,SAAS;AAAA,IACf,WAAW,SAAS;AAAA,IACpB,YAAY,SAAS;AAAA,IACrB,WAAW,MAAM;AAAA,IACjB,QAAQ,KAAK,IAAI;AAAA,IACjB,GAAI,MAAM,gBAAgB,EAAE,eAAe,MAAM,cAAc,IAAI,CAAC;AAAA,IACpE,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjC,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,EAC3B;AACA,QAAM,KAAK,GAAG,SAAS,CAAC,EAAE,GAAG,UAAU,IAAI,YAAY,IAAAA,KAAI,OAAO,IAAI,CAAC,GAAG,QAAQ,SAAY,EAAE,YAAY,SAAS,MAAM,SAAS,GAAG,CAAC;AACxI,SAAO,QAAQ,EAAE,MAAM,OAAO,QAAQ,MAAM,IAAI,EAAE,MAAM,KAAK;AAC/D;AAGO,SAAS,eAAe,KAA0C;AACvE,QAAMC,OAAM,CAAC,MAAoC,OAAO,MAAM,WAAW,IAAI;AAC7E,QAAM,YAAY,IAAI,kBAAkB,OAAO,IAAI,mBAAmB,WAAW,IAAI,iBAAiB,CAAC;AACvG,SAAO;AAAA,IACL,IAAI,OAAO,IAAI,EAAE;AAAA,IACjB,MAAM,OAAO,IAAI,QAAQ,EAAE;AAAA,IAC3B,SAASA,KAAI,IAAI,OAAO,KAAK;AAAA,IAC7B,YAAYA,KAAI,IAAI,UAAU;AAAA,IAC9B,kBAAkBA,KAAI,IAAI,gBAAgB;AAAA,IAC1C,gBAAgBA,KAAI,IAAI,cAAc;AAAA,IACtC,WAAWA,KAAI,IAAI,SAAS;AAAA,IAC5B,gBAAgB;AAAA,EAClB;AACF;;;AC9HA,SAAS,YAAY,6BAA6B;AAa3C,SAAS,cAAc,OAAsB,cAAgC;AAClF,SAAO,QAAQ,MAAM,wBAAwB,MAAM,iBAAiB,YAAY;AAClF;AAIO,SAAS,2BAA2B,eAA+B;AACxE,SAAO,OAAO,aAAa;AAC7B;AAIO,SAAS,kBAAkB,SAAyB;AACzD,SAAO,UAAU,OAAO;AAC1B;AAyBO,SAAS,mBAAmB,KAA+E;AAChH,QAAM,SAAS,CAAC,MACd,KAAK,OAAO,MAAM,WAAa,EAA8B,YAAwC,CAAC,IAAI,CAAC;AAC7G,QAAM,OAAO,CAAC,MACZ,OAAO,EAAE,kBAAkB,WAAW,EAAE,gBAAgB;AAC1D,QAAM,gBACJ,KAAK,OAAO,GAAG,CAAC,KAAK,KAAK,OAAO,IAAI,oBAAoB,CAAC,KAAK,KAAK,OAAQ,IAAI,QAAgD,oBAAoB,CAAC;AACvJ,QAAM,aAAa,OAAO,IAAI,aAAa,WAAW,IAAI,WAAW;AACrE,SAAO,EAAE,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC,GAAI,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC,EAAG;AAC9F;AAGO,SAAS,YAAY,KAAmF;AAC7G,QAAM,SAAS,CAAC,UACd,SAAS,OAAO,UAAU,WAAa,MAAkC,YAAwC,CAAC,IAAI,CAAC;AACzH,QAAM,OAAO,CAAC,aACZ,OAAO,SAAS,iBAAiB,WAAW,SAAS,eAAe;AACtE,QAAM,SAAS,IAAI;AACnB,QAAM,eAAe,IAAI,wBAAwB,QAAQ;AACzD,QAAM,eAAe,KAAK,OAAO,GAAG,CAAC,KAAK,KAAK,OAAO,YAAY,CAAC;AACnE,QAAM,iBAAiB,OAAO,IAAI,iBAAiB,WAC/C,IAAI,eACJ,OAAQ,cAAsD,iBAAiB,WAC7E,OAAQ,aAAyC,YAAY,IAC7D;AACN,SAAO,EAAE,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC,GAAI,kBAAkB,kBAAkB,OAAO,IAAI,MAAM,EAAE,EAAE;AAC/G;AAKO,SAAS,sBAAsB,OAAkC;AACtE,QAAM,MAAM,MAAM,MAAM,UAAU,CAAC;AACnC,QAAM,OAAO,YAAY,GAAG;AAC5B,MAAI,KAAK,cAAc;AACrB,QAAI,MAAM,SAAS,8BACd,MAAM,SAAS,kBAAkB,IAAI,mBAAmB,uBAAwB;AACnF,aAAO,EAAE,MAAM,aAAa,cAAc,KAAK,cAAc,kBAAkB,KAAK,iBAAiB;AAAA,IACvG;AACA,QAAI,MAAM,SAAS,kBAAmB,QAAO,EAAE,MAAM,gBAAgB,cAAc,KAAK,cAAc,QAAQ,WAAW;AACzH,QAAI,MAAM,SAAS,gCAAiC,QAAO,EAAE,MAAM,gBAAgB,cAAc,KAAK,cAAc,QAAQ,WAAW;AACvI,WAAO,EAAE,MAAM,WAAW,MAAM,MAAM,KAAK;AAAA,EAC7C;AACA,QAAM,MAAM,mBAAmB,GAAG;AAClC,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK,gBAAgB;AACnB,YAAM,QAAU,IAAI,OAA+C,QAAuD,CAAC;AAC3H,YAAM,YAAa,MAAM,CAAC,GAAG,QAAgD;AAC7E,YAAM,YAAY,OAAO,cAAc,WAAW,YAAY,MAAO;AACrE,YAAM,OAAO,IAAI,mBAAmB,wBAAwB,kBAAkB;AAC9E,aAAO,EAAE,MAAM,GAAG,KAAK,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC,EAAG;AAAA,IAC3E;AAAA,IACA,KAAK;AACH,aAAO,EAAE,MAAM,YAAY,GAAG,IAAI;AAAA,IACpC,KAAK;AACH,aAAO,EAAE,MAAM,YAAY,GAAG,IAAI;AAAA,IACpC;AACE,aAAO,EAAE,MAAM,WAAW,MAAM,MAAM,KAAK;AAAA,EAC/C;AACF;AAOO,SAAS,kBAAkB,eAAuB,WAA6E;AACpI,SAAO;AAAA,IACL,GAAI,kBAAkB,cAAc,EAAE,QAAQ,uBAAgC,IAAI,CAAC;AAAA,IACnF,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,EACjD;AACF;AAGO,SAAS,aAAa,WAA0C;AACrE,SAAO,EAAE,UAAU;AACrB;AAIO,SAAS,gBAAwC;AACtD,SAAO,EAAE,QAAQ,WAAW;AAC9B;AAGO,SAAS,gBAAoC;AAClD,SAAO,EAAE,UAAU,KAAK;AAC1B;;;AC9IO,IAAM,kCAAkC;AAExC,IAAM,wBAAwB;;;ACHrC,IAAMC,WAAU,IAAI,YAAY;AAEhC,SAASC,gBAAe,OAAwB;AAC9C,MAAI,UAAU,QAAQ,OAAO,UAAU,aAAa,OAAO,UAAU,YAAY,OAAO,UAAU,UAAU;AAC1G,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B;AACA,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,IAAI,MAAM,IAAIA,eAAc,EAAE,KAAK,GAAG,CAAC;AACxE,MAAI,OAAO,UAAU,SAAU,OAAM,IAAI,UAAU,8CAA8C;AACjG,QAAMC,UAAS;AACf,QAAM,UAAU,OAAO,KAAKA,OAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ;AAC1D,UAAM,OAAOA,QAAO,GAAG;AACvB,WAAO,SAAS,SAAY,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,GAAG,CAAC,IAAID,gBAAe,IAAI,CAAC,EAAE;AAAA,EACpF,CAAC;AACD,SAAO,IAAI,QAAQ,KAAK,GAAG,CAAC;AAC9B;AAGO,SAAS,uBAAuB,OAAwB;AAC7D,SAAOA,gBAAe,KAAK;AAC7B;AAGA,eAAsB,oBAAoB,UAAoC;AAC5E,QAAM,SAAS,MAAM,OAAO,OAAO,OAAO,WAAWD,SAAQ,OAAO,uBAAuB,QAAQ,CAAC,CAAC;AACrG,SAAO,UAAU,MAAM,KAAK,IAAI,WAAW,MAAM,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AAC5G;AAGA,eAAsB,4BAA4B,UAAqE;AACrH,SAAO,EAAE,UAAU,QAAQ,MAAM,oBAAoB,QAAQ,EAAE;AACjE;;;ACnBA,IAAMG,MAAK;AACX,IAAM,aAAa;AACnB,IAAM,WAAW;AACjB,IAAMC,YAAW;AACjB,IAAM,mBAAmB,CAAC,UAA2BA,UAAS,KAAK,KAAK;AAGjE,SAAS,wBAAwB,OAAuB;AAC7D,SAAO,sBAAsB,KAAK;AACpC;AAQO,SAAS,+BAA+B,OAA0C;AACvF,QAAM,SAAmB,CAAC;AAC1B,QAAM,OAAO,SAAS,OAAO,UAAU,WAAW,QAAmC,CAAC;AACtF,MAAI,KAAK,kBAAkB,gCAAiC,QAAO,KAAK,kCAAkC;AAC1G,QAAM,WAAW,OAAO,KAAK,QAAQ;AACrC,QAAM,cAAc,OAAO,KAAK,WAAW;AAC3C,MAAI,CAAC,OAAO,cAAc,QAAQ,KAAK,WAAW,EAAG,QAAO,KAAK,8CAA8C;AAC/G,MAAI,CAAC,OAAO,SAAS,WAAW,KAAK,eAAe,EAAG,QAAO,KAAK,iDAAiD;AACpH,QAAM,SAAS,KAAK,UAAU,OAAO,KAAK,WAAW,WAAW,KAAK,SAAoC,CAAC;AAC1G,QAAM,SAAS,KAAK,UAAU,OAAO,KAAK,WAAW,WAAW,KAAK,SAAoC,CAAC;AAC1G,QAAM,WAAW,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AACnE,QAAM,cAAc,OAAO,OAAO,UAAU,WAAW,OAAO,MAAM,KAAK,IAAI;AAC7E,QAAM,YAAY,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;AAC5E,QAAM,cAAc,OAAO,OAAO,gBAAgB,WAAW,OAAO,cAAc;AAClF,MAAI,CAACD,IAAG,KAAK,QAAQ,EAAG,QAAO,KAAK,6CAA6C;AACjF,MAAI,CAAC,eAAe,YAAY,SAAS,IAAK,QAAO,KAAK,gDAAgD;AAC1G,MAAI,CAACA,IAAG,KAAK,SAAS,EAAG,QAAO,KAAK,iDAAiD;AACtF,MAAI,CAACA,IAAG,KAAK,WAAW,EAAG,QAAO,KAAK,mDAAmD;AAC1F,MAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,EAAG,QAAO,KAAK,kCAAkC;AAC/E,QAAM,YAAY,MAAM,QAAQ,KAAK,MAAM,IAAI,KAAK,SAAS,CAAC;AAC9D,MAAI,UAAU,SAAS,WAAY,QAAO,KAAK,oCAAoC,UAAU,UAAU;AACvG,QAAM,SAAgC,CAAC;AACvC,QAAM,UAAU,oBAAI,IAAY;AAChC,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,CAAC,OAAO,GAAG,KAAK,UAAU,MAAM,GAAG,UAAU,EAAE,QAAQ,GAAG;AACnE,UAAM,QAAQ,OAAO,OAAO,QAAQ,WAAW,MAAiC,CAAC;AACjF,UAAME,MAAK,OAAO,MAAM,OAAO,WAAW,MAAM,KAAK;AACrD,UAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,MAAM,MAAM,KAAK,IAAI;AACrE,UAAM,aAAa,wBAAwB,KAAK;AAChD,UAAM,WAAW,MAAM;AACvB,UAAM,OAAO,OAAO,MAAM,SAAS,WAAW,MAAM,KAAK,KAAK,IAAI;AAClE,UAAM,YAAY,MAAM,cAAc,SAAY,SAAY,OAAO,MAAM,SAAS;AACpF,QAAI,CAACF,IAAG,KAAKE,GAAE,EAAG,QAAO,KAAK,mBAAmB,KAAK,4BAA4B;AAClF,QAAI,QAAQ,IAAIA,GAAE,EAAG,QAAO,KAAK,+BAA+BA,GAAE,GAAG;AACrE,QAAI,CAAC,iBAAiB,UAAU,EAAG,QAAO,KAAK,mBAAmB,KAAK,uBAAuB;AAC9F,QAAI,WAAW,IAAI,UAAU,EAAG,QAAO,KAAK,kCAAkC,UAAU,GAAG;AAC3F,QAAI,aAAa,qBAAqB,aAAa,qBAAqB;AACtE,aAAO,KAAK,mBAAmB,KAAK,uBAAuB;AAAA,IAC7D;AACA,QAAI,QAAQ,KAAK,SAAS,SAAU,QAAO,KAAK,mBAAmB,KAAK,oBAAoB;AAC5F,QAAI,cAAc,WAAc,CAAC,OAAO,SAAS,SAAS,KAAK,aAAa,IAAI;AAC9E,aAAO,KAAK,mBAAmB,KAAK,wCAAwC;AAAA,IAC9E;AACA,YAAQ,IAAIA,GAAE;AACd,eAAW,IAAI,UAAU;AACzB,WAAO,KAAK;AAAA,MACV,IAAAA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,IACjD,CAAC;AAAA,EACH;AACA,MAAI,OAAO,OAAQ,QAAO,EAAE,IAAI,OAAO,OAAO;AAC9C,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,MACL,eAAe;AAAA,MACf;AAAA,MACA;AAAA,MACA,QAAQ,EAAE,OAAO,UAAU,OAAO,YAAY;AAAA,MAC9C,QAAQ,EAAE,WAAW,YAAY;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;AAGA,eAAsB,6BAA6B,UAAmE;AACpH,QAAM,UAAU,+BAA+B,QAAQ;AACvD,MAAI,CAAC,QAAQ,GAAI,OAAM,IAAI,UAAU,qCAAqC,QAAQ,OAAO,KAAK,IAAI,CAAC,EAAE;AACrG,SAAO,EAAE,UAAU,QAAQ,OAAO,QAAQ,MAAM,oBAAoB,QAAQ,KAAK,EAAE;AACrF;AAqBA,IAAM,OAAO,CAAC,UAAmD,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AAEjG,SAAS,QAAQ,KAAwD;AACvE,MAAI,OAAO,IAAI,OAAO,YAAY,OAAO,IAAI,oBAAoB,SAAU,QAAO;AAClF,MAAI,IAAI,gBAAgB,WAAW,IAAI,gBAAgB,SAAU,QAAO;AACxE,MAAI,IAAI,aAAa,qBAAqB,IAAI,aAAa,oBAAqB,QAAO;AACvF,SAAO;AACT;AAGA,eAAsB,mBACpB,IACA,UACA,OACA,KACmC;AACnC,QAAM,kBAAkB,wBAAwB,KAAK;AACrD,MAAI,CAAC,iBAAiB,eAAe,EAAG,QAAO;AAC/C,QAAM,SAAS,MAAM,GAAG,MAAM,EAAE,iBAAiB,EAAE,GAAG,EAAE,OAAO,EAAE,gBAAgB,GAAG,OAAO,IAAI,EAAE,EAAE,CAAC;AACpG,QAAM,SAAS,KAAK,OAAO,eAAe,EACvC,IAAI,OAAO,EACX,OAAO,CAAC,UAAsC;AAAA,IAC7C,SAAS,MAAM,aAAa,YAAY,MAAM,WAAW,QAAQ,CAAC,MAAM,cACvE,CAAC,MAAM,aAAa,MAAM,YAAY,QAAQ,CAAC,MAAM;AAAA,EACxD,CAAC,EACA,KAAK,CAAC,GAAG,MAAM;AACd,UAAM,QAAQ,OAAO,EAAE,gBAAgB,OAAO,IAAI,OAAO,EAAE,gBAAgB,OAAO;AAClF,WAAO,SAAS,EAAE,YAAY,EAAE;AAAA,EAClC,CAAC;AACH,SAAO,OAAO,CAAC,KAAK;AACtB;AAcA,eAAe,qBACb,IACA,UACA,UACA,aACkB;AAClB,QAAM,QAAQ,EAAE,UAAU,UAAU,YAAY;AAChD,MAAI,GAAG,WAAW;AAChB,WAAO,QAAQ,MAAM,GAAG,UAAU,2BAA2B,EAAE,OAAO,KAAK,GAAG,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC,IAAI;AAAA,EAC1G;AACA,QAAM,QAAQ,MAAM,GAAG,MAAM,EAAE,yBAAyB,CAAC,EAAE,CAAC;AAC5D,SAAO,KAAK,MAAM,uBAAuB,EAAE,KAAK,CAAC,QAC/C,IAAI,aAAa,YAAY,IAAI,aAAa,YAAY,IAAI,gBAAgB,WAAW;AAC7F;AAGA,eAAsB,4BACpB,IACA,UACA,UACA,aAC2C;AAC3C,MAAI,CAAC,MAAM,qBAAqB,IAAI,UAAU,UAAU,WAAW,EAAG,QAAO;AAC7E,QAAM,SAAS,MAAM,GAAG,MAAM,EAAE,yBAAyB,EAAE,GAAG;AAAA,IAC5D,OAAO,EAAE,UAAU,UAAU,YAAY;AAAA,IAAG,OAAO,EAAE,UAAU,OAAO;AAAA,IAAG,OAAO;AAAA,EAClF,EAAE,EAAE,CAAC;AACL,QAAM,MAAM,KAAK,OAAO,uBAAuB,EAC5C,KAAK,CAAC,GAAG,MAAM,OAAO,EAAE,YAAY,CAAC,IAAI,OAAO,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC;AACtE,SAAO,MAAM,MAA8C;AAC7D;AAGA,eAAsB,2BACpB,IACA,UACA,UACA,YACe;AACf,QAAM,EAAE,UAAU,OAAO,IAAI;AAC7B,QAAM,UAAU,MAAM,MAAM,GAAG,MAAM,EAAE,iBAAiB,EAAE,GAAG;AAAA,IAC3D,OAAO,EAAE,aAAa,UAAU,UAAU,SAAS,OAAO,OAAO,UAAU,SAAS,OAAO,UAAU;AAAA,IACrG,OAAO;AAAA,EACT,EAAE,EAAE,CAAC,GAAG,eAAe;AACvB,QAAM,cAAc,IAAI,IAAI,SAAS,OAAO,IAAI,CAAC,UAAU,oBAAoB,SAAS,OAAO,KAAK,IAAI,MAAM,EAAE,EAAE,CAAC;AACnH,QAAM,MAAc,CAAC;AACrB,aAAW,OAAO,SAAS;AACzB,UAAMA,MAAK,OAAO,IAAI,MAAM,EAAE;AAC9B,QAAIA,OAAM,CAAC,YAAY,IAAIA,GAAE,EAAG,KAAI,KAAK,EAAE,GAAG,UAAU,IAAI,mBAAmB,IAAAA,KAAI,OAAO;AAAA,MACxF,QAAQ;AAAA,MAAO,WAAW;AAAA,MAAY,WAAW,SAAS,OAAO;AAAA,MACjE,WAAW;AAAA,MAAY,WAAW,SAAS,OAAO;AAAA,IACpD,EAAE,CAAC;AAAA,EACL;AACA,aAAW,SAAS,SAAS,QAAQ;AACnC,UAAMA,MAAK,oBAAoB,SAAS,OAAO,KAAK,IAAI,MAAM,EAAE;AAChE,UAAM,WAAW,QAAQ,KAAK,CAAC,QAAQ,IAAI,OAAOA,GAAE;AACpD,QAAI,KAAK,EAAE,GAAG,UAAU,IAAI,mBAAmB,IAAAA,KAAI,OAAO;AAAA,MACxD,IAAAA;AAAA,MACA,eAAe,MAAM;AAAA,MACrB,aAAa;AAAA,MACb,UAAU,SAAS,OAAO;AAAA,MAC1B,UAAU,SAAS,OAAO;AAAA,MAC1B,OAAO,MAAM;AAAA,MACb,iBAAiB,wBAAwB,MAAM,KAAK;AAAA,MACpD,UAAU,MAAM;AAAA,MAChB,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,MACzC,GAAI,MAAM,YAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;AAAA,MACxD,QAAQ;AAAA,MACR,gBAAgB,SAAS;AAAA,MACzB,WAAW,OAAO,UAAU,aAAa,UAAU;AAAA,MACnD,WAAW,OAAO,UAAU,aAAa,SAAS,OAAO,KAAK;AAAA,MAC9D,WAAW;AAAA,MACX,WAAW,SAAS,OAAO;AAAA,IAC7B,EAAE,CAAC;AACH,UAAM,UAAU;AAAA,MACd,GAAI,CAAC,MAAM,QAAQ,UAAU,SAAS,SAAY,CAAC,MAAM,IAAI,CAAC;AAAA,MAC9D,GAAI,MAAM,cAAc,UAAa,UAAU,cAAc,SAAY,CAAC,WAAW,IAAI,CAAC;AAAA,IAC5F;AACA,QAAI,QAAQ,OAAQ,KAAI,KAAK,EAAE,GAAG,WAAW,IAAI,mBAAmB,IAAAA,KAAI,OAAO,QAAQ,CAAC;AAAA,EAC1F;AACA,MAAI,UAAU,OAAQ,KAAI,KAAK,EAAE,GAAG,UAAU,IAAI,2BAA2B,IAAI,SAAS,IAAI,OAAO,EAAE,QAAQ,MAAM,EAAE,CAAC;AACxH,QAAM,aAAa,sBAAsB,SAAS,OAAO,KAAK,IAAI,SAAS,OAAO,WAAW,IAAI,SAAS,QAAQ;AAClH,MAAI,KAAK,EAAE,GAAG,UAAU,IAAI,2BAA2B,IAAI,YAAY,OAAO;AAAA,IAC5E,IAAI;AAAA,IACJ,UAAU,SAAS,OAAO;AAAA,IAC1B,UAAU,SAAS,OAAO;AAAA,IAC1B,aAAa,SAAS,OAAO;AAAA,IAC7B,UAAU,SAAS;AAAA,IACnB;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,EACF,EAAE,CAAC;AACH,QAAM,GAAG,SAAS,KAAK,EAAE,YAAY,oBAAoB,SAAS,OAAO,KAAK,IAAI,SAAS,OAAO,WAAW,IAAI,SAAS,QAAQ,IAAI,MAAM,GAAG,CAAC;AAClJ;;;AC1PO,SAAS,wBAAwB,OAOZ;AAC1B,MAAI,MAAM,WAAW,WAAY,QAAO;AACxC,MAAI,MAAM,iBAAiB;AACzB,QAAI,CAAC,MAAM,QAAS,QAAO;AAC3B,QAAI,MAAM,WAAW,MAAM,eAAe;AACxC,aAAO,MAAM,sBAAsB,mBAAmB;AAAA,IACxD;AACA,WAAO;AAAA,EACT;AACA,MAAI,CAAC,MAAM,QAAS,QAAO;AAC3B,MAAI,MAAM,WAAW,MAAM,eAAe;AACxC,WAAO,MAAM,sBAAsB,mBAAmB;AAAA,EACxD;AACA,MAAI,QAAQ,MAAM,QAAQ,MAAM,QAAQ,EAAG,QAAO;AAClD,SAAO;AACT;;;AC5BO,IAAM,6BAA6B;AAEnC,IAAM,kBAAkB;AAqC/B,IAAMC,MAAK;AACX,IAAM,QAAQ;AACd,IAAM,WAAW;AACjB,IAAMC,UAAS,CAAC,UACd,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAAI,QAAmC;AACnG,IAAM,OAAO,CAAC,OAAgB,MAAc,QAAkB,QAAwB;AACpF,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,GAAG;AAAE,WAAO,KAAK,GAAG,IAAI,cAAc;AAAG,WAAO;AAAA,EAAI;AACjG,MAAI,MAAM,KAAK,EAAE,SAAS,IAAK,QAAO,KAAK,GAAG,IAAI,oBAAoB,GAAG,aAAa;AACtF,SAAO,MAAM,KAAK;AACpB;AAGO,SAAS,yBAAyB,OAAgB,SAAmD;AAC1G,QAAM,SAAmB,CAAC;AAC1B,QAAM,OAAOA,QAAO,KAAK;AACzB,MAAI,CAAC,KAAM,QAAO,EAAE,IAAI,OAAO,QAAQ,CAAC,uCAAuC,EAAE;AACjF,aAAW,OAAO,OAAO,KAAK,IAAI,EAAG,KAAI,QAAQ,mBAAmB,QAAQ,SAAU,QAAO,KAAK,uBAAuB,GAAG,mBAAmB;AAC/I,MAAI,KAAK,kBAAkB,2BAA4B,QAAO,KAAK,6CAA6C;AAChH,MAAI,CAAC,MAAM,QAAQ,KAAK,MAAM,EAAG,QAAO,KAAK,6CAA6C;AAC1F,QAAM,YAAY,MAAM,QAAQ,KAAK,MAAM,IAAI,KAAK,SAAS,CAAC;AAC9D,MAAI,UAAU,SAAS,gBAAiB,QAAO,KAAK,+CAA+C,eAAe,UAAU;AAC5H,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,SAAsB,CAAC;AAC7B,aAAW,CAAC,OAAO,GAAG,KAAK,UAAU,MAAM,GAAG,eAAe,EAAE,QAAQ,GAAG;AACxE,UAAM,OAAO,8BAA8B,KAAK;AAChD,UAAM,OAAOA,QAAO,GAAG;AACvB,QAAI,CAAC,MAAM;AAAE,aAAO,KAAK,GAAG,IAAI,oBAAoB;AAAG;AAAA,IAAU;AACjE,UAAMC,WAAU,oBAAI,IAAI,CAAC,MAAM,UAAU,eAAe,iBAAiB,cAAc,YAAY,2BAA2B,cAAc,eAAe,SAAS,eAAe,UAAU,CAAC;AAC9L,eAAW,OAAO,OAAO,KAAK,IAAI,EAAG,KAAI,CAACA,SAAQ,IAAI,GAAG,EAAG,QAAO,KAAK,GAAG,IAAI,IAAI,GAAG,mBAAmB;AACzG,UAAMC,MAAK,KAAK,KAAK,IAAI,GAAG,IAAI,OAAO,QAAQ,EAAE;AACjD,QAAIA,OAAM,CAACH,IAAG,KAAKG,GAAE,EAAG,QAAO,KAAK,GAAG,IAAI,uCAAuC;AAClF,QAAI,IAAI,IAAIA,GAAE,EAAG,QAAO,KAAK,GAAG,IAAI,mBAAmBA,GAAE,GAAG;AAC5D,QAAI,IAAIA,GAAE;AACV,UAAM,YAAYF,QAAO,KAAK,MAAM;AACpC,QAAI,SAA0B,EAAE,MAAM,eAAe,gBAAgB,UAAU;AAC/E,QAAI,WAAW,SAAS,QAAQ;AAC9B,YAAM,SAAS,KAAK,UAAU,QAAQ,GAAG,IAAI,kBAAkB,QAAQ,EAAE;AACzE,UAAI,CAAC,QAAQ,IAAI,MAAM,EAAG,QAAO,KAAK,GAAG,IAAI,+CAA+C;AAC5F,eAAS,EAAE,MAAM,QAAQ,OAAO;AAAA,IAClC,WAAW,WAAW,SAAS,eAAe;AAC5C,YAAM,iBAAiB,KAAK,UAAU,gBAAgB,GAAG,IAAI,0BAA0B,QAAQ,EAAE;AACjG,UAAI,kBAAkB,CAACD,IAAG,KAAK,cAAc,EAAG,QAAO,KAAK,GAAG,IAAI,0DAA0D;AAC7H,eAAS,EAAE,MAAM,eAAe,eAAe;AAAA,IACjD,MAAO,QAAO,KAAK,GAAG,IAAI,0CAA0C;AACpE,QAAI,KAAK,gBAAgB,cAAc,KAAK,gBAAgB,eAAgB,QAAO,KAAK,GAAG,IAAI,+CAA+C;AAC9I,UAAM,gBAAgB,KAAK,KAAK,eAAe,GAAG,IAAI,kBAAkB,QAAQ,GAAG;AACnF,QAAI,iBAAiB,CAAC,MAAM,KAAK,aAAa,EAAG,QAAO,KAAK,GAAG,IAAI,+CAA+C;AACnH,QAAI,CAAC,OAAO,cAAc,KAAK,UAAU,KAAK,OAAO,KAAK,UAAU,IAAI,KAAK,OAAO,KAAK,UAAU,IAAI,IAAa,QAAO,KAAK,GAAG,IAAI,sDAAsD;AAC7L,UAAM,WAAW,OAAO,KAAK,aAAa,WAAW,KAAK,SAAS,KAAK,EAAE,YAAY,IAAI;AAC1F,QAAI,CAAC,SAAS,KAAK,QAAQ,EAAG,QAAO,KAAK,GAAG,IAAI,iDAAiD;AAClG,UAAM,WAAW,OAAO,KAAK,uBAAuB;AACpD,QAAI,CAAC,OAAO,cAAc,QAAQ,KAAK,WAAW,KAAK,WAAW,KAAO,QAAO,KAAK,GAAG,IAAI,4DAA4D;AACxJ,UAAM,aAAa,KAAK,eAAe,SAAY,SAAY,OAAO,KAAK,UAAU;AACrF,UAAM,cAAc,KAAK,gBAAgB,SAAY,SAAY,OAAO,KAAK,WAAW;AACxF,QAAI,eAAe,WAAc,CAAC,OAAO,cAAc,UAAU,KAAK,aAAa,GAAI,QAAO,KAAK,GAAG,IAAI,wCAAwC;AAClJ,QAAI,gBAAgB,WAAc,CAAC,OAAO,cAAc,WAAW,KAAK,cAAc,GAAI,QAAO,KAAK,GAAG,IAAI,yCAAyC;AACtJ,QAAI,eAAe,UAAa,gBAAgB,UAAa,eAAe,WAAY,QAAO,KAAK,GAAG,IAAI,qCAAqC;AAChJ,WAAO,KAAK;AAAA,MACV,IAAAG;AAAA,MAAI;AAAA,MAAQ,aAAa,KAAK;AAAA,MAAyC;AAAA,MACvE,YAAY,OAAO,KAAK,UAAU;AAAA,MAAG;AAAA,MAAU,yBAAyB;AAAA,MACxE,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,MAAI,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,MACxG,OAAO,KAAK,KAAK,OAAO,GAAG,IAAI,UAAU,QAAQ,GAAG;AAAA,MAAG,aAAa,KAAK,KAAK,aAAa,GAAG,IAAI,gBAAgB,QAAQ,GAAK;AAAA,MAC/H,UAAU,KAAK,KAAK,UAAU,GAAG,IAAI,aAAa,QAAQ,GAAG;AAAA,IAC/D,CAAC;AAAA,EACH;AACA,SAAO,OAAO,SAAS,EAAE,IAAI,OAAO,OAAO,IAAI,EAAE,IAAI,MAAM,OAAO,EAAE,eAAe,GAAG,OAAO,EAAE;AACjG;AAGO,IAAM,kBAAkB,CAAC,OAAkB,SAC/C,CAAC,MAAM,cAAc,MAAM,cAAc,SAAS,CAAC,MAAM,eAAe,MAAM,cAAc;AAGxF,SAAS,iBAAiB,SAAuC,KAAgC;AACtG,UAAQ,SAAS,UAAU,CAAC,GAAG,OAAO,CAAC,UAAU,gBAAgB,OAAO,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,eAAe,SAAS,QAAQ,SAAS,GAAG,MAAM,MAAM,KAAK;AACpJ;AAGO,SAAS,cAAc,SAAuC,SAAiB,KAA+B;AACnH,SAAO,SAAS,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,WAAW,gBAAgB,OAAO,GAAG,CAAC,KAAK;AACjG;;;ACxGA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACuHA,IAAM,uBAAoE;AAAA,EAC/E,QAAQ,CAAC,QAAQ,SAAS,aAAa,YAAY,SAAS,UAAU;AAAA,EACtE,SAAS,CAAC,QAAQ,UAAU,YAAY,YAAY,YAAY,OAAO;AACzE;;;ADjGO,SAAS,kBAAkB,QAA+C;AAC/E,QAAM,QAAQ,OAAO,MAAM,YAAY;AACvC,QAAM,WAAW,CAAC,OAAO,WAAW,OAAO,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EAAE,KAAK;AACpF,QAAM,QAAiC,EAAE,MAAM,OAAO,QAAQ,YAAY,OAAO,MAAM;AACvF,MAAI,MAAM,SAAS,GAAI,OAAM,OAAO;AACpC,MAAI,OAAO,UAAW,OAAM,YAAY,OAAO;AAC/C,MAAI,OAAO,SAAU,OAAM,WAAW,OAAO;AAC7C,MAAI,OAAO,MAAO,OAAM,QAAQ,OAAO;AACvC,MAAI,OAAO,SAAU,OAAM,WAAW,OAAO;AAC7C,SAAO;AACT;AAEA,SAAS,UAAU,OAAuB;AACxC,MAAI,IAAI;AACR,MAAI,IAAI;AACR,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK,GAAG;AACxC,UAAM,IAAI,MAAM,WAAW,CAAC;AAC5B,QAAI,KAAK,KAAK,IAAI,GAAG,QAAU;AAC/B,QAAI,KAAK,KAAK,IAAI,GAAG,UAAU;AAAA,EACjC;AACA,SAAO,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC,IAAI,MAAM,GAAG,SAAS,EAAE,CAAC;AAC3D;AAIO,SAAS,iBAAiB,MAAc,aAAqB,UAA2B;AAC7F,QAAM,UAAU,KAAK,YAAY;AACjC,QAAM,WAAW,gBAAgB,KAAK,WAAW;AACjD,QAAM,SAAS,WAAW,WAAW,SAAS,YAAY,CAAC,IAAI,OAAO,KAAK,WAAW,OAAO;AAC7F,QAAM,MAAM,GAAG,MAAM,IAAI,WAAW;AACpC,MAAI,YAAY,IAAI,UAAU,GAAI,QAAO;AACzC,SAAO,WAAW,QAAQ,MAAM,GAAG,EAAE,CAAC,IAAI,UAAU,GAAG,YAAY,EAAE,KAAS,IAAI,KAAS,WAAW,EAAE,CAAC;AAC3G;AAIO,SAAS,sBACdC,SACA,mBAAmB,iBACK;AACxB,MAAI,WAAWA,WAAUA,QAAO,YAAY,GAAG;AAC7C,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAUA,QAAO,OAAO;AAAA,MACxB,gBAAgBA,QAAO,OAAO;AAAA,MAC9B,MAAMA,QAAO;AAAA,MACb,OAAOA,QAAO;AAAA,IAChB;AAAA,EACF;AACA,MAAI,WAAWA,SAAQ;AACrB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,gBAAgBA,QAAO;AAAA,MACvB,MAAMA,QAAO;AAAA,MACb,OAAOA,QAAO;AAAA,IAChB;AAAA,EACF;AACA,MAAI,UAAUA,WAAUA,QAAO,SAAS,WAAW;AACjD,UAAM,QAAiC,EAAE,MAAMA,QAAO,KAAK;AAC3D,eAAW,OAAO,CAAC,UAAU,YAAY,YAAY,YAAY,OAAO,GAAY;AAClF,UAAIA,QAAO,GAAG,EAAG,OAAM,GAAG,IAAIA,QAAO,GAAG;AAAA,IAC1C;AACA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,gBAAgBA,QAAO;AAAA,MACvB,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT,UAAU;AAAA,IACV,gBAAgBA,QAAO;AAAA,IACvB,MAAM;AAAA,IACN,OAAO,kBAAkBA,OAAM;AAAA,EACjC;AACF;AAIO,SAAS,oBACd,KACAA,SACA,QACA,UACc;AACd,MAAI,OAAO,UAAU,CAAC,OAAO,OAAOA,QAAO,IAAI,GAAG;AAChD,UAAM,IAAI,MAAM,GAAG,OAAO,IAAI,qBAAqBA,QAAO,IAAI,WAAW;AAAA,EAC3E;AACA,QAAM,MAAM,IAAI,KAAKA,QAAO,IAAI;AAChC,QAAM,SAAS,OAAO,SAASA,QAAO,IAAI,KAAK,qBAAqBA,QAAO,IAAI;AAC/E,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,GAAG,OAAO,IAAI,8CAA8CA,QAAO,IAAI,WAAW;AAAA,EACpG;AACA,QAAM,YAAY,IAAI,aAAa;AACnC,QAAM,QAAiC,CAAC;AACxC,aAAW,SAAS,oBAAI,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,GAAG;AACnD,UAAM,QAAQA,QAAO,SAAS,KAAK;AACnC,QAAI,UAAU,OAAW,OAAM,KAAK,IAAI;AAAA,EAC1C;AACA,MAAI,MAAM,SAAS,MAAM,OAAW,OAAM,SAAS,IAAIA,QAAO;AAC9D,SAAO,WACH,EAAE,SAAS,GAAG,QAAQ,EAAE,QAAQ,UAAU,UAAUA,QAAO,GAAG,GAAG,MAAMA,QAAO,MAAM,MAAM,IAC1F,EAAE,SAAS,GAAG,MAAMA,QAAO,MAAM,aAAaA,QAAO,IAAI,MAAM;AACrE;AAKA,eAAe,aACb,MACA,MAC+B;AAC/B,QAAM,QAAQ,KAAK,MAAM,YAAY;AACrC,QAAM,UAAU,EAAE,KAAK,KAAK,KAAK,IAAI,KAAK,IAAa,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM;AACxF,QAAM,EAAE,WAAW,IAAI,MAAM,KAAK,GAAG,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,UAAU,cAAc,MAAM,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC;AAC9H,QAAM,WAAW,aAAa,CAAC;AAC/B,MAAI,YAAY,OAAO,SAAS,OAAO,UAAU;AAC/C,UAAM,aAAa,SAAS,EAAE,IAAI,SAAS,IAAI,OAAO,KAAK,MAAM,CAAC;AAClE,WAAO,EAAE,UAAU,SAAS,GAAG;AAAA,EACjC;AACA,QAAM,UAAU,MAAM,aAAa,SAAS,EAAE,MAAM,UAAU,OAAO,KAAK,OAAO,YAAY,KAAK,WAAW,CAAC;AAC9G,SAAO,EAAE,UAAU,QAAQ,GAAG;AAChC;AAEA,eAAe,iBACb,MACAA,SACA,KAC8C;AAC9C,QAAM,aAAa,MAAM;AAAA,IACvB,EAAE,KAAK,KAAK,KAAK,IAAI,KAAK,IAAa,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM;AAAA,IACxEA,QAAO;AAAA,IACPA,QAAO;AAAA,EACT;AACA,MAAI,WAAY,QAAO;AACvB,QAAM,SAAS,MAAM,KAAK,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC;AACnF,QAAM,WAAW,OAAO,UAAU,CAAC,GAAG;AACtC,MAAI,OAAO,aAAa,UAAU;AAChC,UAAM,QAAQ,MAAM,KAAK,GAAG,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,SAAS,GAAG,OAAO,EAAE,EAAE,EAAE,CAAC;AAC9F,QAAI,MAAM,aAAa,CAAC,EAAG,QAAO,MAAM,WAAW,CAAC;AAAA,EACtD;AACA,QAAM,MAAM,KAAK,IAAI,KAAKA,QAAO,IAAI;AACrC,QAAM,aAAa,IAAI;AACvB,MAAI,cAAc,OAAOA,QAAO,MAAM,UAAU,MAAM,UAAU;AAC9D,UAAM,eAAeA,QAAO,MAAM,UAAU,EAAE,YAAY;AAC1D,UAAM,QAAQ,MAAM,KAAK,GAAG,MAAM;AAAA,MAChC,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,MAAMA,QAAO,MAAM,aAAa,GAAG,OAAO,EAAE,EAAE;AAAA,IAC5E,CAAC;AACD,QAAI,MAAM,aAAa,CAAC,EAAG,QAAO,MAAM,WAAW,CAAC;AAAA,EACtD;AACA,QAAM,SAASA,QAAO,MAAM;AAC5B,QAAM,aAAa,IAAI,OAAO,QAAQ;AACtC,MAAI,OAAO,WAAW,YAAY,YAAY;AAC5C,UAAM,QAAQ,MAAM,KAAK,GAAG,MAAM;AAAA,MAChC,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,MAAMA,QAAO,MAAM,CAAC,UAAU,GAAG,OAAO,GAAG,OAAO,EAAE,EAAE;AAAA,IACpF,CAAC;AACD,QAAI,MAAM,aAAa,CAAC,EAAG,QAAO,MAAM,WAAW,CAAC;AAAA,EACtD;AACA,QAAM,YAAY,IAAI,aAAa;AACnC,QAAM,OAAOA,QAAO,MAAM,SAAS;AACnC,MAAIA,QAAO,SAAS,aAAa,OAAO,SAAS,YAAY,KAAK,KAAK,GAAG;AACxE,UAAM,QAAQ,MAAM,KAAK,GAAG,MAAM;AAAA,MAChC,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,MAAMA,QAAO,MAAM,MAAM,KAAK,KAAK,EAAE,GAAG,OAAO,EAAE,EAAE;AAAA,IACjF,CAAC;AACD,QAAI,MAAM,aAAa,CAAC,EAAG,QAAO,MAAM,WAAW,CAAC;AAAA,EACtD;AACA,SAAO;AACT;AAOA,eAAsB,oBACpB,MACA,QACA,UAAqD,CAAC,GACvB;AAC/B,QAAMA,UAAS,sBAAsB,QAAQ,QAAQ,QAAQ;AAC7D,MAAI,CAACA,QAAO,KAAK,KAAK,KAAK,CAACA,QAAO,SAAS,KAAK,KAAK,CAACA,QAAO,eAAe,KAAK,GAAG;AACnF,UAAM,IAAI,MAAM,8DAA8D;AAAA,EAChF;AACA,MAAI,QAAQ,YAAY,QAAQ,aAAaA,QAAO,UAAU;AAC5D,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,QAAM,MAAM,iBAAiBA,QAAO,MAAMA,QAAO,gBAAgBA,QAAO,YAAY,IAAIA,QAAO,WAAW,MAAS;AACnH,QAAM,UAAU,EAAE,KAAK,KAAK,KAAK,IAAI,KAAK,IAAa,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM;AACxF,QAAM,WAAW,MAAM,iBAAiB,MAAMA,SAAQ,GAAG;AACzD,MAAI;AACJ,MAAI,YAAY,OAAO,SAAS,OAAO,UAAU;AAG/C,UAAM,aAAa,SAAS,EAAE,IAAI,SAAS,IAAI,OAAOA,QAAO,MAAM,CAAC;AACpE,eAAW,SAAS;AAAA,EACtB,OAAO;AAGL,eAAW,WAAW,UAAU,GAAGA,QAAO,QAAQ,KAASA,QAAO,IAAI,KAASA,QAAO,cAAc,EAAE,CAAC;AACvG,UAAM,aAAa,EAAE,GAAG,SAAS,OAAO,MAAM,SAAS,GAAG;AAAA,MACxD,MAAMA,QAAO;AAAA,MACb,OAAOA,QAAO;AAAA,MACd,YAAY,gBAAgB,GAAG;AAAA,IACjC,CAAC;AAAA,EACH;AACA,QAAM,KAAK,GAAG;AAAA,IACZ,CAAC,EAAE,GAAG,UAAU,IAAI,WAAW,IAAI,KAAK,OAAO,EAAE,KAAK,GAAG,QAAQ,IAAI,GAAG,IAAI,UAAU,KAAK,WAAW,KAAK,IAAI,EAAE,EAAE,CAAC;AAAA,IACpH,EAAE,YAAY,aAAa,GAAG,IAAI,QAAQ,GAAG;AAAA,EAC/C;AACA,QAAM,mBAAmB,SAAS;AAAA,IAChC;AAAA,IACA,UAAUA,QAAO;AAAA,IACjB,gBAAgBA,QAAO;AAAA,IACvB,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC5D,gBAAgBA,QAAO;AAAA,EACzB,CAAC;AACD,SAAO,EAAE,SAAS;AACpB;AA0BA,eAAsB,iBAAiB,MAAsB,WAAqD;AAChH,QAAM,OAAO,kBAAkB;AAAA,IAC7B,OAAO,UAAU;AAAA,IACjB,WAAW,UAAU;AAAA,IACrB,UAAU,UAAU;AAAA,IACpB,OAAO,UAAU;AAAA,IACjB,UAAU,UAAU;AAAA,IACpB,aAAa,UAAU;AAAA,EACzB,CAAC;AACD,QAAM,aAAa,SAAS,UAAU,aAAa;AACnD,QAAM,QAAQ,UAAU,SAAS,CAAC;AAClC,MAAI,OAAO,KAAK,KAAK,EAAE,WAAW,EAAG,QAAO,aAAa,MAAM,EAAE,OAAO,UAAU,OAAO,OAAO,MAAM,WAAW,CAAC;AAClH,MAAI;AACF,WAAO,MAAM,aAAa,MAAM,EAAE,OAAO,UAAU,OAAO,OAAO,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC;AAAA,EACtG,QAAQ;AACN,WAAO,aAAa,MAAM,EAAE,OAAO,UAAU,OAAO,OAAO,MAAM,WAAW,CAAC;AAAA,EAC/E;AACF;;;AEzSA,SAAS,gBAAAC,eAAc,gBAAAC,eAAc,UAAU,oBAAoB;AAKnE,IAAM,MAAM,CAAC,MAAwB,OAAO,MAAM,WAAW,IAAI,KAAK,OAAO,KAAK,OAAO,CAAC;AAsBnF,SAAS,mBAAmB,SAAkB,KAAuD;AAC1G,QAAM,QAAQ,kBAAkB;AAAA,IAC9B,OAAO,IAAI,IAAI,KAAK;AAAA,IACpB,WAAW,IAAI,IAAI,SAAS,KAAK;AAAA,IACjC,UAAU,IAAI,IAAI,QAAQ,KAAK;AAAA,IAC/B,OAAO,IAAI,IAAI,KAAK,KAAK;AAAA,IACzB,UAAU,IAAI,IAAI,QAAQ,KAAK;AAAA,IAC/B,aAAa,IAAI,IAAI,EAAE;AAAA,EACzB,CAAC;AACD,aAAW,KAAK,QAAQ,YAAY,WAAW;AAC7C,QAAI,IAAI,CAAC,MAAM,OAAW,OAAM,CAAC,IAAI,IAAI,CAAC;AAAA,EAC5C;AACA,MAAI,IAAI,OAAO,OAAW,OAAM,gBAAgB,IAAI,IAAI,EAAE;AAC1D,SAAO;AACT;AAKA,SAAS,eAAe,KAAuD;AAC7E,QAAM,SAAS,IAAI,IAAI,MAAM;AAC7B,QAAM,OAAO,QAAQ,IAAI,oBAAoB,KAAK,WAAW;AAC7D,QAAM,gBAAgB,WAAW,aAAa,aAAa,IAAI,aAAa,OAAO,aAAa,OAAO,WAAW;AAClH,QAAM,OAAgC,EAAE,cAAc;AACtD,MAAI,IAAI,iBAAkB,MAAK,mBAAmB,IAAI,IAAI,gBAAgB;AAC1E,MAAI,IAAI,qBAAsB,MAAK,iBAAiB,IAAI,IAAI,oBAAoB;AAChF,MAAI,OAAO,IAAI,cAAc,SAAU,MAAK,YAAY,IAAI;AAC5D,SAAO;AACT;AAOA,eAAsB,qBACpB,MACA,MACwB;AACxB,QAAM,WAAW,IAAI,KAAK,IAAI,KAAK,EAAE,YAAY;AACjD,MAAI,CAAC,SAAU,QAAO;AAEtB,QAAM,aAAa,EAAE,KAAK,KAAK,KAAK,IAAI,KAAK,IAAa,KAAK,KAAK,KAAK,OAAO,KAAK,MAAM;AAC3F,QAAM,QAAQ,mBAAmB,KAAK,SAAS,KAAK,GAAG;AAEvD,QAAM,EAAE,WAAW,IAAI,MAAM,KAAK,GAAG,MAAM;AAAA,IACzC,YAAY,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,UAAU,cAAc,SAAS,GAAG,OAAO,EAAE,EAAE;AAAA,EACnF,CAAC;AACD,QAAM,WAAW,aAAa,CAAC,KAAK;AACpC,QAAM,QAAQ,KAAK,SAAS;AAE5B,MAAI;AACJ,MAAI,YAAY,OAAO,SAAS,OAAO,UAAU;AAC/C,eAAW,SAAS;AACpB,UAAMC,cAAa,YAAY,EAAE,IAAI,UAAU,MAAM,CAAC;AAAA,EACxD,OAAO;AACL,UAAM,UAAU,MAAMC,cAAa,YAAY,EAAE,MAAM,UAAU,OAAO,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAG,CAAC;AACrG,eAAW,QAAQ;AAAA,EACrB;AAKA,MAAI,YAAY,SAAS,SAAS,UAAU,OAAO;AACjD,UAAM,SAAS,YAAY,EAAE,IAAI,UAAU,IAAI,OAAO,UAAU,UAAU,YAAY,aAAa,QAAQ,IAAI,KAAK,GAAG,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,EACjJ;AAEA,QAAM,KAAK,GAAG,SAAS,CAAC,EAAE,GAAG,UAAU,IAAI,cAAc,IAAI,UAAU,OAAO,eAAe,KAAK,GAAG,EAAE,CAAC,CAAC;AAKzG,QAAM,aAAa,YAAY,EAAE,UAAU,OAAO,UAAU,YAAY,YAAY,QAAQ,IAAI,QAAQ,GAAG,CAAC,EAAE,MAAM,MAAM,MAAS;AAEnI,SAAO;AACT;AAKA,eAAsB,YAAY,MAA2H;AAC3J,QAAM,OAAO,MAAM,KAAK,GAAG,MAAM;AAAA,IAC/B,cAAc,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,OAAO,GAAG,OAAO,IAAK,EAAE;AAAA,IACjE,QAAQ,EAAE,GAAG,EAAE,OAAO,IAAK,EAAE;AAAA,EAC/B,CAAC;AACD,QAAM,OAAO,oBAAI,IAAY;AAC7B,MAAI,SAAS;AACb,QAAM,SAAkD,CAAC;AAEzD,QAAM,MAAM,OAAO,KAA8B,UAAkC;AACjF,UAAM,MAAM,IAAI,IAAI,KAAK,EAAE,YAAY;AACvC,QAAI,CAAC,OAAO,KAAK,IAAI,GAAG,EAAG;AAC3B,SAAK,IAAI,GAAG;AACZ,QAAI;AACF,YAAM,qBAAqB,MAAM,EAAE,KAAK,MAAM,CAAC;AAC/C,gBAAU;AAAA,IACZ,SAAS,KAAK;AACZ,aAAO,KAAK,EAAE,OAAO,KAAK,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,EAAE,CAAC;AAAA,IACrF;AAAA,EACF;AAEA,aAAW,KAAM,KAAK,gBAAgB,CAAC,EAAsC,OAAM,IAAI,GAAG,IAAI,EAAE,MAAM,CAAC;AACvG,aAAW,KAAM,KAAK,UAAU,CAAC,GAAsC;AACrE,QAAI,EAAE,YAAY,KAAM;AACxB,UAAM,IAAI,EAAE,OAAO,EAAE,OAAO,WAAW,IAAI,EAAE,IAAI,EAAE,CAAC;AAAA,EACtD;AACA,SAAO,EAAE,QAAQ,OAAO;AAC1B;;;ACzIO,SAAS,aACd,QACA,KACA,QAAQ,IACqC;AAC7C,QAAM,OAAO,IAAI;AACjB,QAAM,MAAM;AACZ,QAAM,QAAQ,MAAM,QAAQ;AAC5B,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,OAAO,EAAE,WAAW,QAAQ,IAAI,MAAM,OAAO,EAAE,EAAE;AACnG,aAAW,KAAK,QAAQ;AACtB,QAAI,CAAC,OAAO,SAAS,EAAE,CAAC,KAAK,EAAE,IAAI,SAAS,EAAE,IAAI,IAAK;AACvD,UAAM,MAAM,KAAK,IAAI,QAAQ,GAAG,KAAK,OAAO,EAAE,IAAI,SAAS,IAAI,CAAC;AAChE,UAAM,SAAS,QAAQ,GAAG;AAC1B,QAAI,OAAQ,QAAO,SAAS,OAAO,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI;AAAA,EAC3D;AACA,SAAO;AACT;AAeA,SAAS,aACP,QACA,KACA,OACA,UACuB;AACvB,QAAM,QAAQ,MAAM,QAAQ;AAC5B,QAAM,gBAAgB,QAAQ,QAAQ;AACtC,QAAM,UAAU,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,MAAM,CAAC;AACrD,QAAM,WAAW,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,MAAM,CAAC;AACtD,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,OAAO,SAAS,MAAM,CAAC,KAAK,CAAC,OAAO,SAAS,MAAM,CAAC,EAAG;AAC5D,QAAI,MAAM,KAAK,SAAS,MAAM,KAAK,KAAK;AACtC,YAAM,QAAQ,KAAK,IAAI,QAAQ,GAAG,KAAK,OAAO,MAAM,IAAI,SAAS,QAAQ,CAAC;AAC1E,cAAQ,KAAK,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM;AAAA,IACjD,WAAW,MAAM,KAAK,iBAAiB,MAAM,IAAI,OAAO;AACtD,YAAM,QAAQ,KAAK,IAAI,QAAQ,GAAG,KAAK,OAAO,MAAM,IAAI,iBAAiB,QAAQ,CAAC;AAClF,eAAS,KAAK,KAAK,SAAS,KAAK,KAAK,KAAK,MAAM;AAAA,IACnD;AAAA,EACF;AACA,QAAM,SAAS,QAAQ,IAAI,CAAC,GAAG,UAC7B,IAAI,KAAK,QAAQ,QAAQ,QAAQ,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAC/D,SAAO,EAAE,QAAQ,SAAS,SAAS;AACrC;AAGO,SAAS,oBACd,QACA,KACqB;AACrB,QAAM,MAAM;AACZ,SAAO;AAAA,IACL,KAAK,aAAa,QAAQ,KAAK,GAAG,GAAG;AAAA,IACrC,KAAK,aAAa,QAAQ,KAAK,GAAG,IAAI,GAAG;AAAA,EAC3C;AACF;AAKO,SAAS,eAAe,KAAsC;AACnE,QAAM,QAAU,IAAI,OAAiE,QAAQ,CAAC;AAC9F,MAAI,QAAQ;AACZ,aAAW,MAAM,OAAO;AACtB,UAAM,QAAS,GAAG,SAAS,CAAC;AAC5B,UAAM,OAAO,MAAM,eAAe,MAAO,GAAG,YAAuB;AACnE,aAAS,MAAM,WAAW,aAAa,UAAU,MAAM,KAAK;AAAA,EAC9D;AACA,SAAO;AACT;;;ACpFA,SAAS,eAAe,yBAAAC,8BAAuD;AA2C/E,eAAsB,WACpB,IACA,QACA,MACA,QACA,gBACuB;AACvB,SAAO;AAAA,IACL,EAAE,WAAW,GAAG;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB,EAAE,eAAe,IAAI,CAAC;AAAA,EACzC;AACF;;;ACzCA,IAAM,OAAO,CAAC,WACZ,WAAW,MAAM,EAAE,IAAI,MAAM,QAAQ,SAAS,KAAK,IAAI,EAAE,IAAI,OAAO,OAAO;AAetE,SAAS,mBAAmB,OAA0E;AAC3G,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,eAAe,MAAM;AAAA,MACrB,QAAQ;AAAA,MACR,GAAI,MAAM,cAAc,EAAE,cAAc,MAAM,YAAY,IAAI,CAAC;AAAA,MAC/D,GAAI,MAAM,iBAAiB,EAAE,iBAAiB,MAAM,eAAe,IAAI,CAAC;AAAA,IAC1E;AAAA,EACF;AACF;AAKA,eAAsB,sBACpB,WACA,OACA,YAA0B,OACJ;AACtB,QAAM,EAAE,MAAM,KAAK,IAAI,mBAAmB,KAAK;AAC/C,QAAM,MAAM,MAAM,UAAU,wBAAwB,IAAI,IAAI;AAAA,IAC1D,QAAQ;AAAA,IACR,SAAS,EAAE,eAAe,UAAU,SAAS,IAAI,gBAAgB,mBAAmB;AAAA,IACpF,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,SAAO,IAAI,KAAK,EAAE,IAAI,MAAM,QAAQ,IAAI,OAAO,IAAI,KAAK,IAAI,MAAM;AACpE;AAoBO,SAAS,iBAAiB,OAAwE;AACvG,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,eAAe,CAAC,MAAM,KAAK;AAAA,MAC3B,2BAA2B;AAAA,MAC3B,GAAI,MAAM,YAAY,EAAE,YAAY,MAAM,UAAU,IAAI,CAAC;AAAA,MACzD,GAAI,MAAM,WAAW,EAAE,WAAW,MAAM,SAAS,IAAI,CAAC;AAAA,MACtD,GAAI,MAAM,mBAAmB,SAAY,EAAE,iBAAiB,MAAM,eAAe,IAAI,CAAC;AAAA,MACtF,GAAI,MAAM,oBAAoB,SAAY,EAAE,kBAAkB,MAAM,gBAAgB,IAAI,CAAC;AAAA,IAC3F;AAAA,EACF;AACF;AAWA,eAAsB,wBACpB,WACA,QACA,OACA,YAA0B,OACR;AAClB,QAAM,MAAM,MAAM,UAAU,kCAAkC,mBAAmB,MAAM,CAAC,aAAa;AAAA,IACnG,QAAQ;AAAA,IACR,SAAS,EAAE,eAAe,UAAU,SAAS,IAAI,gBAAgB,mBAAmB;AAAA,IACpF,MAAM,KAAK,UAAU;AAAA,MACnB,GAAI,MAAM,mBAAmB,SAAY,EAAE,iBAAiB,MAAM,eAAe,IAAI,CAAC;AAAA,MACtF,GAAI,MAAM,oBAAoB,SAAY,EAAE,kBAAkB,MAAM,gBAAgB,IAAI,CAAC;AAAA,IAC3F,CAAC;AAAA,EACH,CAAC;AACD,SAAO,IAAI;AACb;AAQA,eAAsB,+BACpB,WACA,OACA,OACA,YAA0B,OACR;AAClB,QAAM,OAAO,EAAE,eAAe,UAAU,SAAS,GAAG;AACpD,QAAM,QAAQ,MAAM,UAAU,gDAAgD,mBAAmB,KAAK,CAAC,YAAY,EAAE,SAAS,KAAK,CAAC;AACpI,MAAI,CAAC,MAAM,GAAI,QAAO;AACtB,QAAM,QAAS,MAAM,MAAM,KAAK,EAAE,MAAM,MAAM,IAAI;AAClD,QAAMC,MAAK,MAAM,QAAQ,KAAK,KAAK,OAAO,MAAM,CAAC,GAAG,OAAO,WAAW,MAAM,CAAC,EAAE,KAAK;AACpF,MAAI,CAACA,IAAI,QAAO;AAChB,SAAO,wBAAwB,WAAWA,KAAI,OAAO,SAAS;AAChE;AAOA,eAAsB,gBACpB,WACA,OACA,YAA0B,OACJ;AACtB,QAAM,EAAE,MAAM,KAAK,IAAI,iBAAiB,KAAK;AAC7C,QAAM,MAAM,MAAM,UAAU,wBAAwB,IAAI,IAAI;AAAA,IAC1D,QAAQ;AAAA,IACR,SAAS,EAAE,eAAe,UAAU,SAAS,IAAI,gBAAgB,mBAAmB;AAAA,IACpF,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,MAAI,IAAI,GAAI,QAAO,EAAE,IAAI,MAAM,QAAQ,IAAI,OAAO;AAClD,QAAM,SAAS,KAAK,IAAI,MAAM;AAC9B,QAAM,SAAS,MAAM,kBAAkB;AAAA,IACrC,GAAI,MAAM,mBAAmB,SAAY,EAAE,gBAAgB,MAAM,eAAe,IAAI,CAAC;AAAA,IACrF,GAAI,MAAM,oBAAoB,SAAY,EAAE,iBAAiB,MAAM,gBAAgB,IAAI,CAAC;AAAA,EAC1F;AACA,MACE,CAAC,OAAO,WACP,OAAO,mBAAmB,UAAa,OAAO,oBAAoB,OACnE,QAAO;AACT,QAAM,YAAY,MAAM,+BAA+B,WAAW,MAAM,OAAO;AAAA,IAC7E,GAAI,OAAO,mBAAmB,SAAY,EAAE,gBAAgB,OAAO,eAAe,IAAI,CAAC;AAAA,IACvF,GAAI,OAAO,oBAAoB,SAAY,EAAE,iBAAiB,OAAO,gBAAgB,IAAI,CAAC;AAAA,EAC5F,GAAG,SAAS,EAAE,MAAM,MAAM,KAAK;AAC/B,SAAO,EAAE,GAAG,QAAQ,UAAU;AAChC;;;ACxKA,IAAM,YAAY;AAClB,IAAM,eAAe;AACrB,IAAM,OAAO;AAwBb,SAAS,SAAS,GAAyC;AACzD,MAAI,OAAO,EAAE,OAAO,SAAU,QAAO;AACrC,QAAM,KAAM,EAAE,mBAAmB,CAAC;AAClC,QAAM,kBAAmB,EAAE,oBAAoB,CAAC;AAChD,QAAM,aAAa,gBAAgB;AACnC,QAAM,UAAU,cAAc,OAAO,eAAe,YAAY,CAAC,MAAM,QAAQ,UAAU,IACrF,aACA,CAAC;AACL,QAAM,gBAAgB,OAAO,gBAAgB,kBAAkB,WAC3D,gBAAgB,gBAChB;AACJ,QAAM,OAAO,OAAO,GAAG,SAAS,YAAY,GAAG,OAAO,GAAG,OAAO;AAChE,QAAM,QAAQ,EAAE,kBAAkB,CAAC,GAAG;AACtC,SAAO;AAAA,IACL,IAAI,EAAE;AAAA,IACN,OAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,IAC3C;AAAA,IACA,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA,GAAI,gBAAgB,EAAE,cAAc,IAAI,CAAC;AAAA,EAC3C;AACF;AAEA,eAAe,SAAS,MAAc,WAAmB,WAA2C;AAClG,QAAM,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,IAAI,IAAI,EAAE,SAAS,EAAE,eAAe,UAAU,SAAS,GAAG,EAAE,CAAC;AACxG,MAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,aAAa,IAAI,WAAM,IAAI,MAAM,EAAE;AAChE,SAAO,IAAI,KAAK;AAClB;AAKA,eAAsB,oBAAoB,WAAmB,OAAe,YAA0B,OAAwC;AAC5I,QAAM,OAAO,MAAM,SAAS,2BAA2B,mBAAmB,KAAK,CAAC,YAAY,WAAW,SAAS,EAAE,MAAM,MAAM,IAAI;AAClI,QAAM,OAAO,MAAM,QAAQ,IAAI,IAAK,KAAK,CAAC,IAAiC;AAC3E,SAAO,OAAO,SAAS,IAAI,IAAI;AACjC;AAIA,eAAsB,aAAa,WAAmBC,KAAY,YAA0B,OAAwC;AAClI,QAAM,OAAO,MAAM,SAAS,aAAa,mBAAmBA,GAAE,CAAC,IAAI,WAAW,SAAS,EAAE,MAAM,MAAM,IAAI;AACzG,SAAO,OAAO,SAAS,IAAoB,IAAI;AACjD;AAOA,eAAsB,eAAe,WAAmB,YAA0B,OAAmC;AACnH,QAAM,MAAyB,CAAC;AAChC,WAAS,SAAS,KAAK,UAAU,MAAM;AACrC,UAAM,OAAO,MAAM,SAAS,mBAAmB,IAAI,WAAW,MAAM,IAAI,WAAW,SAAS;AAC5F,UAAM,OAAO,MAAM,QAAQ,IAAI,IAAK,OAA0B,CAAC;AAC/D,eAAW,KAAK,MAAM;AACpB,YAAMC,UAAS,SAAS,CAAC;AACzB,UAAIA,QAAQ,KAAI,KAAKA,OAAM;AAAA,IAC7B;AACA,QAAI,KAAK,SAAS,KAAM;AAAA,EAC1B;AACA,SAAO;AACT;AAKA,eAAsB,aAAa,WAAmBD,KAAY,MAAc,YAA0B,OAAyB;AACjI,QAAM,MAAM,MAAM,UAAU,GAAG,SAAS,aAAa,mBAAmBA,GAAE,CAAC,aAAa;AAAA,IACtF,QAAQ;AAAA,IACR,SAAS,EAAE,eAAe,UAAU,SAAS,IAAI,gBAAgB,mBAAmB;AAAA,IACpF,MAAM,KAAK,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,CAAC;AAAA,EACpD,CAAC;AACD,SAAO,IAAI;AACb;;;AClBO,IAAM,mBAA0C;AAAA,EACrD,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,KAAK;AAAA,EACL,UAAU;AAAA,IACR;AAAA,MACE,KAAK;AAAA,MACL,aAAa;AAAA,MACb,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP;AAAA;AAAA;AAAA;AAAA;AAAA,MAKE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,MACT,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS;AAAA,MACT,MAAM;AAAA,MACN,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA,OAAO;AAAA,IACL;AAAA,MACE,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,QAAQ;AAAA;AAAA,MAER,QAAQ,CAAC,MAAM,SAAS,QAAQ,UAAU;AAAA,MAC1C,SAAS;AAAA,MACT,UAAU;AAAA,IACZ;AAAA,IACA;AAAA,MACE,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,QAAQ;AAAA;AAAA;AAAA,MAGR,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,EACF;AAAA,EACA,WAAW;AAAA,IACT,OAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,IACA,KAAK;AAAA,MACH;AAAA,MACA;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;ACzFO,SAAS,mBAAmB,KAA4C;AAC7E,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,WAAW,IAAI,aAAa;AAAA,IAC5B,UAAU,IAAI,YAAY;AAAA,IAC1B,OAAO,IAAI,SAAS;AAAA,IACpB,QAAQ,IAAI;AAAA,IACZ,WAAW,IAAI,aAAa;AAAA,IAC5B,aAAa,IAAI,eAAe;AAAA,IAChC,MAAM,QAAQ,IAAI,oBAAoB,KAAK,IAAI,WAAW;AAAA,IAC1D,WAAW,IAAI,aAAa;AAAA,IAC5B,UAAU,IAAI,aAAa;AAAA,IAC3B,QAAQ,IAAI,UAAU;AAAA,EACxB;AACF;AAKO,SAAS,kBACd,KACA,SACA,iBACmB;AACnB,QAAM,UAAU,mBAAmB,GAAG;AACtC,MAAI,YAAY,IAAI,aAAa;AACjC,MAAI,UAAyB;AAC7B,MAAI,WAAW;AACf,MAAI,SAAS;AACX,eAAW,QAAQ,YAAY;AAC/B,QAAI,QAAQ,WAAW,aAAa;AAClC,kBAAY,QAAQ,WAAW;AAC/B,gBAAU,QAAQ,WAAW;AAAA,IAC/B,OAAO;AACL,kBAAY;AAAA,IACd;AAAA,EACF;AACA,SAAO,EAAE,GAAG,SAAS,WAAW,SAAS,SAAS;AACpD;AAWO,SAAS,cACd,MACA,MACe;AACf,SAAO;AAAA,IACL,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK,SAAS;AAAA,IACrB,MAAM,KAAK;AAAA,IACX,YAAY,KAAK;AAAA,IACjB,aAAa,KAAK;AAAA,EACpB;AACF;;;ACzHA,SAAS,WAAW,KAAqB;AACvC,SAAO,IAAI,WAAW,IAAI,IAAI,MAAM,KAAK,GAAG;AAC9C;AAKA,SAAS,WAAW,OAAuB;AACzC,SAAO,MAAM,QAAQ,YAAY,EAAE,EAAE,KAAK;AAC5C;AAEA,SAAS,aAAa,SAAuD;AAC3E,QAAM,QAAkB,CAAC;AACzB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,WAAW,CAAC,CAAC,GAAG;AACxD,QAAI,OAAO,UAAU,YAAY,MAAM,KAAK,EAAG,OAAM,KAAK,GAAG,WAAW,GAAG,CAAC,KAAK,WAAW,KAAK,CAAC,GAAG;AAAA,EACvG;AACA,SAAO;AACT;AAEA,IAAM,aAAuD;AAAA,EAC3D,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,UAAU;AAAA,EACV,MAAM;AAAA,EACN,WAAW;AAAA,EACX,WAAW;AAAA,EACX,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,MAAM;AAAA,EACN,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,eAAe;AAAA,EACf,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,aAAa;AAAA,EACb,kBAAkB;AACpB;AAEA,SAAS,cAAc,QAAkD;AACvE,SAAO,OAAO,QAAQ,UAAU,CAAC,CAAC,EAAE;AAAA,IAAQ,CAAC,CAAC,KAAK,KAAK,MACtD,OAAO,UAAU,YAAY,MAAM,KAAK,IACpC,CAAC,GAAG,WAAW,GAA+B,CAAC,KAAK,WAAW,KAAK,CAAC,GAAG,IACxE,CAAC;AAAA,EACP;AACF;AAYO,SAAS,YACd,OACA,UAAiC,CAAC,GAC1B;AACR,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,QAAQ,CAAC,GAAG,aAAa,MAAM,OAAO,GAAG,GAAG,cAAc,MAAM,MAAM,CAAC;AAC7E,QAAM,QAAQ,MAAM;AACpB,MAAI,OAAO,QAAS,OAAM,KAAK,sBAAsB,WAAW,MAAM,OAAO,CAAC,GAAG;AACjF,MAAI,OAAO,KAAM,OAAM,KAAK,mBAAmB,WAAW,MAAM,IAAI,CAAC,GAAG;AACxE,MAAI,OAAO,QAAS,OAAM,KAAK,sBAAsB,WAAW,MAAM,OAAO,CAAC,GAAG;AACjF,QAAM,OAAO,CAAC,GAAG,aAAa,MAAM,WAAW,GAAG,GAAG,cAAc,MAAM,UAAU,CAAC;AACpF,QAAM,SAAS,aAAa,MAAM,aAAa;AAC/C,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,eAAe,aAAa,UAAU,6BAA6B,GAAG,QAAQ;AACpF,QAAM,iBAAiB,aAAa,UAChC,oCACA,GAAG,QAAQ;AAEf,MAAI,MAAM,MAAM,SAAS,GAAG,QAAQ;AAAA,IAAS,MAAM,KAAK,MAAM,CAAC;AAAA;AAAA,IAAU;AACzE,MAAI,KAAK,QAAQ;AACf,UAAM,QAAQ;AAAA,IAAQ,KAAK,KAAK,MAAM,CAAC;AAAA;AACvC,WAAO,GAAG,YAAY,IAAI,KAAK;AAAA;AAAA,IAA8C,cAAc,IAAI,KAAK;AAAA;AAAA;AAAA,EACtG;AACA,MAAI,OAAO,QAAQ;AACjB,UAAM,iBAAiB,aAAa,UAChC,eACA,GAAG,QAAQ,eAAe,QAAQ;AACtC,WAAO,GAAG,cAAc;AAAA;AAAA,IAAgC,OAAO,KAAK,MAAM,CAAC;AAAA;AAAA;AAAA,EAC7E;AACA,SAAO;AACT;AAaO,SAAS,uBACd,UACA,OAAqB,CAAC,GACR;AACd,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,EAAE,GAAG,SAAS,OAAO,GAAG,KAAK,QAAQ;AAAA,IAC9C,aAAa,EAAE,GAAG,SAAS,MAAM,GAAG,KAAK,YAAY;AAAA,IACrD,eAAe,EAAE,GAAG,SAAS,MAAM,GAAG,KAAK,cAAc;AAAA,EAC3D;AACF;;;AChGO,SAAS,eAAe,SAA8B,KAAsB;AACjF,SAAO,QAAQ,WAAW,eAAe,QAAQ,QAAQ,aAAa,MAAM,QAAQ,WAAW,KAAK,MAAM;AAC5G;AAUO,SAAS,kBACdE,WACA,QACA,KACqB;AACrB,QAAM,UAAU,IAAI,IAAI,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;AACzD,QAAM,YAAiC,CAAC;AACxC,aAAW,KAAKA,WAAU;AACxB,QAAI,CAAC,eAAe,GAAG,GAAG,KAAK,CAAC,EAAE,cAAe;AACjD,UAAM,IAAI,QAAQ,IAAI,EAAE,aAAa;AACrC,QAAI,CAAC,KAAK,EAAE,WAAW,aAAa;AAClC,gBAAU,KAAK;AAAA,QACb,WAAW,EAAE;AAAA,QACb,eAAe,EAAE;AAAA,QACjB,MAAM;AAAA,QACN,cAAc,EAAE,QAAQ,aAAa,OAAO,QAAQ,qBAAqB,IAAI;AAAA,QAC7E,kBAAkB,EAAE,WAAW,GAAG,aAAa,GAAG;AAAA,MACpD,CAAC;AAAA,IACH,WAAW,EAAE,YAAY,UAAa,EAAE,YAAY,EAAE,SAAS;AAC7D,YAAM,YAAY,EAAE,SAAS,MAAM,EAAE,WAAW;AAChD,gBAAU,KAAK;AAAA,QACb,WAAW,EAAE;AAAA,QACb,eAAe,EAAE;AAAA,QACjB,MAAM;AAAA,QACN,cAAc,EAAE,SAAS,EAAE,SAAS,OAAO,EAAE,SAAS,EAAE,UAAU,UAAU,OAAO,QAAQ,qBAAqB,IAAI;AAAA,QACpH,kBAAkB,EAAE,WAAW,EAAE,QAAQ;AAAA,MAC3C,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO;AACT;;;ACjDO,IAAM,sBAA0C;AAAA,EACrD,aAAa;AAAA,EACb,MAAM,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA,EACpB,WAAW;AAAA,EACX,SAAS;AAAA,EACT,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,YAAY;AAAA,EACZ,iBAAiB;AACnB;AAEA,SAAS,gBAAgB,IAAqB;AAC5C,MAAI;AACF,QAAI,KAAK,eAAe,QAAW,EAAE,UAAU,GAAG,CAAC;AACnD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAQO,SAAS,kBAAkB,QAAgD;AAChF,QAAM,SAAS,mBAAmB,MAAM;AACxC,MAAI,OAAO,GAAI,QAAO,OAAO;AAC7B,QAAM,SAAS,OAAO,QAAQ,OAAO,MAAM,EACxC,IAAI,CAAC,CAAC,OAAO,OAAO,MAAM,GAAG,KAAK,KAAK,OAAO,EAAE,EAChD,KAAK,GAAG;AACX,QAAM,IAAI,MAAM,eAAe,MAAM,EAAE;AACzC;AAYO,SAAS,mBACd,QACmF;AACnF,QAAM,IAAI,UAAU,CAAC;AACrB,QAAM,IAAwB;AAAA,IAC5B,aAAa,EAAE,eAAe,oBAAoB;AAAA,IAClD,MAAM,EAAE,QAAQ,oBAAoB;AAAA,IACpC,WAAW,EAAE,aAAa,oBAAoB;AAAA,IAC9C,SAAS,EAAE,WAAW,oBAAoB;AAAA,IAC1C,UAAU,EAAE,YAAY,oBAAoB;AAAA,IAC5C,gBAAgB,EAAE,kBAAkB,oBAAoB;AAAA,IACxD,YAAY,EAAE,cAAc,oBAAoB;AAAA,IAChD,iBAAiB,EAAE,mBAAmB,oBAAoB;AAAA,EAC5D;AACA,QAAM,SAA2B,CAAC;AAClC,MAAI,EAAE,EAAE,eAAe,MAAM,EAAE,eAAe,MAAM;AAClD,WAAO,cAAc;AAAA,EACvB;AACA,MAAI,EAAE,EAAE,cAAc,KAAK,EAAE,cAAc,KAAK;AAC9C,WAAO,aAAa;AAAA,EACtB;AACA,MAAI,EAAE,EAAE,kBAAkB,KAAK,EAAE,kBAAkB,MAAM;AACvD,WAAO,iBAAiB;AAAA,EAC1B;AACA,MAAI,EAAE,EAAE,aAAa,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,KAAK;AACrE,WAAO,QAAQ;AAAA,EACjB;AACA,QAAM,OAAO,CAAC,GAAG,EAAE,IAAI;AACvB,MAAI,CAAC,KAAK,OAAQ,QAAO,OAAO;AAAA,WACvB,CAAC,KAAK,MAAM,CAAC,MAAM,OAAO,UAAU,CAAC,KAAK,KAAK,KAAK,KAAK,CAAC,GAAG;AACpE,WAAO,OAAO;AAAA,EAChB;AACA,MAAI,OAAO,EAAE,aAAa,YAAY,CAAC,gBAAgB,EAAE,QAAQ,GAAG;AAClE,WAAO,WAAW,IAAI,OAAO,EAAE,QAAQ,CAAC;AAAA,EAC1C;AACA,MAAI,OAAO,EAAE,oBAAoB,SAAU,QAAO,kBAAkB;AACpE,SAAO,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,EAAE,IAAI,OAAO,OAAO,IAAI,EAAE,IAAI,MAAM,OAAO,EAAE,GAAG,GAAG,KAAK,EAAE;AACpG;AAQO,SAAS,WAAW,KAAa,YAAkD;AACxF,SAAO,EAAE,MAAM,KAAK,IAAI,MAAM,aAAa,MAAW;AACxD;AAGO,SAAS,WAAW,SAAiB,aAA6B;AACvE,SAAO,UAAU,cAAc;AACjC;AAIO,SAAS,gBAAgB,OAAuC,SAA0B;AAC/F,SAAO,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO;AAChD;AAGO,SAAS,cAAc,UAAkB,KAAsE;AACpH,SAAO,SAAS,QAAQ,iBAAiB,IAAI,aAAa,EAAE,EAAE,QAAQ,gBAAgB,IAAI,YAAY,EAAE;AAC1G;AAYO,SAAS,gBAAgB,UAA+F;AAC7H,QAAM,UAAU,UAAU,iBAAiB;AAC3C,SAAO,EAAE,YAAY,QAAQ,OAAO,GAAG,QAAQ;AACjD;AAIO,SAAS,oBAAoB,eAA+B;AACjE,SAAO,eAAe,aAAa;AACrC;AAqBO,SAAS,iBAAiB,GAWf;AAChB,SAAO;AAAA,IACL,IAAI,EAAE;AAAA,IACN,eAAe,EAAE;AAAA,IACjB,SAAS,EAAE;AAAA,IACX,SAAS,EAAE;AAAA,IACX,OAAO,EAAE;AAAA,IACT,UAAU,EAAE;AAAA,IACZ,QAAQ;AAAA,IACR,eAAe,EAAE;AAAA,IACjB,GAAI,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC1C,GAAI,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,IAAI,CAAC;AAAA,IAC7C,OAAO;AAAA,IACP,WAAW,EAAE;AAAA,EACf;AACF;AAUO,SAAS,wBAAwB,SAAiB,OAAuC;AAC9F,SAAO,EAAE,SAAS,OAAO,OAAO,OAAO;AACzC;AAYO,SAAS,yBACd,eACA,SACA,UACyB;AACzB,SAAO;AAAA,IACL,WAAW;AAAA,IACX,GAAI,WAAW,EAAE,aAAa,SAAS,IAAI,CAAC;AAAA,IAC5C,GAAI,kBAAkB,mBAAmB,EAAE,QAAQ,iBAA0B,IAAI,CAAC;AAAA,EACpF;AACF;;;ACzOA,SAAS,UAAU,KAA8B,SAA8B;AAC7E,SAAO;AAAA,IACL,IAAI,OAAO,IAAI,MAAM,EAAE;AAAA,IACvB,SAAS,OAAO,IAAI,WAAW,OAAO;AAAA,IACtC,MAAM,OAAO,IAAI,QAAQ,EAAE;AAAA,IAC3B,YAAY,OAAO,IAAI,eAAe,WAAW,IAAI,aAAa;AAAA,IAClE,GAAI,OAAO,IAAI,kBAAkB,YAAY,IAAI,gBAC7C,EAAE,eAAe,IAAI,cAAc,IACnC,CAAC;AAAA,IACL,GAAI,OAAO,IAAI,UAAU,WAAW,EAAE,OAAO,IAAI,MAAM,IAAI,CAAC;AAAA,IAC5D,WAAW,OAAO,IAAI,cAAc,WAAW,IAAI,YAAY;AAAA;AAAA;AAAA,IAG/D,QAAQ,IAAI,WAAW;AAAA,EACzB;AACF;AAQA,eAAsB,UAAU,IAAe,OAA6C;AAC1F,QAAM,UAAU,OAAO,MAAM,MAAM,EAAE;AACrC,MAAIC;AACJ,MAAI;AACF,IAAAA,SAAQ,MAAM,GAAG,MAAM;AAAA,MACrB,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,QAAQ,GAAG,OAAO,EAAE,WAAW,MAAM,GAAG,OAAO,IAAI,EAAE;AAAA,IAC9E,CAAC,GAA8B;AAAA,EACjC,QAAQ;AACN,IAAAA,QAAO;AAAA,EACT;AACA,QAAM,OAAO,MAAM,QAAQA,KAAI,IAC3BA,MAAK,IAAI,CAAC,QAAQ,UAAU,KAAgC,OAAO,CAAC,IACpE,CAAC;AACL,SAAO,aAAa,OAAO,IAAI;AACjC;AAGA,eAAsB,mBACpB,IACA,OACA,cACwB;AACxB,SAAO,eAAe,MAAM,UAAU,IAAI,KAAK,GAAG,OAAO,YAAY;AACvE;;;AClDO,IAAM,gCAAgC;AAEtC,IAAM,sBAAsB;;;ACP5B,IAAM,2BAA2B;AAgExC,IAAM,UAAU;AAChB,IAAM,WAAW,oBAAI,IAA2B,CAAC,YAAY,YAAY,YAAY,CAAC;AACtF,IAAMC,aAAY,oBAAI,IAAI,CAAC,iBAAiB,YAAY,SAAS,kBAAkB,CAAC;AACpF,IAAM,YAAY,oBAAI,IAAI;AAAA,EACxB;AAAA,EAAU;AAAA,EAAW;AAAA,EAAS;AAAA,EAAmB;AAAA,EACjD;AAAA,EAAuB;AAAA,EAAgB;AAAA,EAAqB;AAAA,EAC5D;AAAA,EAAY;AAAA,EAAW;AACzB,CAAC;AACD,IAAM,eAAe,oBAAI,IAAI,CAAC,SAAS,cAAc,CAAC;AACtD,IAAM,gBAAgB,oBAAI,IAAI,CAAC,SAAS,OAAO,CAAC;AAChD,IAAM,YAAY;AAClB,IAAM,eAAe;AACrB,IAAMC,gBAAe;AACrB,IAAM,YAAY;AAElB,IAAM,eAAe,CAAC,UACpB,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC/D,QACA;AAEN,SAAS,kBACP,OACAC,UACA,MACA,QACM;AACN,aAAW,OAAO,OAAO,KAAK,KAAK,GAAG;AACpC,QAAI,CAACA,SAAQ,IAAI,GAAG,EAAG,QAAO,KAAK,GAAG,IAAI,IAAI,GAAG,mBAAmB;AAAA,EACtE;AACF;AAEA,SAAS,cACP,OACA,MACA,QACA,KACA,WAAW,OACS;AACpB,MAAI,UAAU,QAAW;AACvB,QAAI,SAAU,QAAO,KAAK,GAAG,IAAI,cAAc;AAC/C,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,KAAK,GAAG,IAAI,mBAAmB;AACtC,WAAO;AAAA,EACT;AACA,QAAMC,QAAO,MAAM,KAAK;AACxB,MAAI,YAAY,CAACA,MAAM,QAAO,KAAK,GAAG,IAAI,cAAc;AACxD,MAAIA,MAAK,SAAS,IAAK,QAAO,KAAK,GAAG,IAAI,oBAAoB,IAAI,eAAe,OAAO,CAAC,aAAa;AACtG,SAAOA;AACT;AAOO,SAAS,+BACd,OACA,UAA2C,CAAC,GACZ;AAChC,QAAM,SAAmB,CAAC;AAC1B,QAAM,OAAO,aAAa,KAAK;AAC/B,MAAI,CAAC,KAAM,QAAO,EAAE,IAAI,OAAO,QAAQ,CAAC,4BAA4B,EAAE;AACtE,oBAAkB,MAAMH,YAAW,YAAY,MAAM;AACrD,MAAI,KAAK,kBAAkB,EAAG,QAAO,KAAK,kCAAkC;AAC5E,MAAI,KAAK,aAAa,0BAA0B;AAC9C,WAAO,KAAK,8BAA+B,wBAAwB,GAAI;AAAA,EACzE;AACA,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,EAAG,QAAO,KAAK,iCAAiC;AAC7E,QAAM,WAAW,MAAM,QAAQ,KAAK,KAAK,IAAI,KAAK,QAAQ,CAAC;AAC3D,MAAI,MAAM,QAAQ,KAAK,KAAK,KAAK,SAAS,WAAW,EAAG,QAAO,KAAK,+CAA+C;AACnH,MAAI,SAAS,SAAS,UAAW,QAAO,KAAK,mCAAmC,SAAS,UAAU;AAEnG,QAAM,YAAY,IAAI,KAAK,QAAQ,SAAS,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC9E,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAMI,SAAsC,CAAC;AAC7C,aAAW,CAAC,OAAO,GAAG,KAAK,SAAS,MAAM,GAAG,SAAS,EAAE,QAAQ,GAAG;AACjE,UAAM,OAAO,kBAAkB,KAAK;AACpC,UAAM,OAAO,aAAa,GAAG;AAC7B,QAAI,CAAC,MAAM;AACT,aAAO,KAAK,GAAG,IAAI,oBAAoB;AACvC;AAAA,IACF;AACA,sBAAkB,MAAM,WAAW,MAAM,MAAM;AAC/C,UAAM,SAAS,cAAc,KAAK,QAAQ,GAAG,IAAI,WAAW,QAAQ,IAAI,IAAI,KAAK;AACjF,QAAI,UAAU,CAAC,QAAQ,KAAK,MAAM,EAAG,QAAO,KAAK,GAAG,IAAI,2CAA2C;AACnG,QAAI,KAAK,IAAI,MAAM,EAAG,QAAO,KAAK,GAAG,IAAI,uBAAwB,MAAM,GAAI;AAC3E,SAAK,IAAI,MAAM;AACf,QAAI,UAAU,QAAQ,CAAC,UAAU,IAAI,MAAM,EAAG,QAAO,KAAK,GAAG,IAAI,YAAa,MAAM,0BAA2B;AAE/G,UAAM,UAAU,KAAK;AACrB,QAAI,YAAY,WAAc,OAAO,YAAY,YAAY,CAAC,SAAS,IAAI,OAAgC,IAAI;AAC7G,aAAO,KAAK,GAAG,IAAI,oDAAoD;AAAA,IACzE;AACA,UAAM,YAAY,KAAK;AACvB,QAAI,cAAc,WAAc,CAAC,OAAO,UAAU,SAAS,KAAK,OAAO,SAAS,IAAI,KAAK,OAAO,SAAS,IAAI,MAAc;AACzH,aAAO,KAAK,GAAG,IAAI,+DAA+D;AAAA,IACpF;AACA,UAAM,SAAS,UAAU,IAAI,MAAM,GAAG;AACtC,QAAI,OAAO,UAAU,SAAS,KAAK,WAAW,UAAa,OAAO,SAAS,KAAK,QAAQ;AACtF,aAAO,KAAK,GAAG,IAAI,wEAAwE;AAAA,IAC7F;AAEA,QAAI;AACJ,QAAI,KAAK,aAAa,QAAW;AAC/B,UAAI,CAAC,MAAM,QAAQ,KAAK,QAAQ,EAAG,QAAO,KAAK,GAAG,IAAI,4BAA4B;AAAA,WAC7E;AACH,YAAI,KAAK,SAAS,SAAS,aAAc,QAAO,KAAK,GAAG,IAAI,8BAA8B,YAAY,UAAU;AAChH,mBAAW,KAAK,SAAS,MAAM,GAAG,YAAY,EAAE,QAAQ,CAAC,SAAS,iBAAiB;AACjF,gBAAMD,QAAO,cAAc,SAAS,GAAG,IAAI,aAAa,YAAY,KAAK,QAAQ,KAAO,IAAI;AAC5F,iBAAOA,QAAO,CAACA,KAAI,IAAI,CAAC;AAAA,QAC1B,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI;AACJ,QAAI,KAAK,YAAY,QAAW;AAC9B,YAAM,aAAa,aAAa,KAAK,OAAO;AAC5C,UAAI,CAAC,WAAY,QAAO,KAAK,GAAG,IAAI,4BAA4B;AAAA,WAC3D;AACH,0BAAkB,YAAY,cAAc,GAAG,IAAI,YAAY,MAAM;AACrE,cAAM,eAAe,cAAc,WAAW,cAAc,GAAG,IAAI,yBAAyB,QAAQF,eAAc,IAAI;AACtH,cAAM,QAAQ,cAAc,WAAW,OAAO,GAAG,IAAI,kBAAkB,QAAQ,SAAS;AACxF,YAAI,aAAc,WAAU,EAAE,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,GAAI,aAAa;AAAA,MAC1E;AAAA,IACF;AAEA,QAAI;AACJ,QAAI,KAAK,aAAa,QAAW;AAC/B,YAAM,cAAc,aAAa,KAAK,QAAQ;AAC9C,UAAI,CAAC,YAAa,QAAO,KAAK,GAAG,IAAI,6BAA6B;AAAA,WAC7D;AACH,0BAAkB,aAAa,eAAe,GAAG,IAAI,aAAa,MAAM;AACxE,cAAM,QAAQ,YAAY;AAC1B,YAAI,CAAC,OAAO,UAAU,KAAK,KAAK,OAAO,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,KAAW;AAC9E,iBAAO,KAAK,GAAG,IAAI,wDAAwD;AAAA,QAC7E;AACA,cAAM,QAAQ,cAAc,YAAY,OAAO,GAAG,IAAI,mBAAmB,QAAQ,SAAS;AAC1F,YAAI,OAAO,UAAU,KAAK,KAAK,OAAO,KAAK,KAAK,KAAK,OAAO,KAAK,KAAK,KAAW;AAC/E,qBAAW,EAAE,OAAO,OAAO,KAAK,GAAG,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC,EAAG;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAQ,cAAc,KAAK,OAAO,GAAG,IAAI,UAAU,QAAQ,SAAS;AAC1E,UAAM,kBAAkB,cAAc,KAAK,iBAAiB,GAAG,IAAI,oBAAoB,QAAQA,aAAY;AAC3G,UAAM,eAAe,cAAc,KAAK,cAAc,GAAG,IAAI,iBAAiB,QAAQ,SAAS;AAC/F,UAAM,eAAe,cAAc,KAAK,cAAc,GAAG,IAAI,iBAAiB,QAAQ,SAAS;AAC/F,UAAM,oBAAoB,cAAc,KAAK,mBAAmB,GAAG,IAAI,sBAAsB,QAAQA,aAAY;AACjH,UAAM,WAAW,cAAc,KAAK,UAAU,GAAG,IAAI,aAAa,QAAQ,SAAS;AACnF,IAAAG,OAAM,KAAK;AAAA,MACT;AAAA,MACA,GAAI,OAAO,YAAY,YAAY,SAAS,IAAI,OAAgC,IAAI,EAAE,QAA0C,IAAI,CAAC;AAAA,MACrI,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,MACzB,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,MAC7C,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,MACvC,GAAI,OAAO,UAAU,SAAS,IAAI,EAAE,qBAAqB,OAAO,SAAS,EAAE,IAAI,CAAC;AAAA,MAChF,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,MACvC,GAAI,oBAAoB,EAAE,kBAAkB,IAAI,CAAC;AAAA,MACjD,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,MAC/B,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,MAC/B,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IACjC,CAAC;AAAA,EACH;AACA,MAAI,UAAU,MAAM;AAClB,eAAW,UAAU,UAAU,KAAK,GAAG;AACrC,UAAI,CAAC,KAAK,IAAI,MAAM,EAAG,QAAO,KAAK,2CAA4C,MAAM,GAAI;AAAA,IAC3F;AAAA,EACF;AACA,QAAM,mBAAmB,cAAc,KAAK,kBAAkB,6BAA6B,QAAQH,aAAY;AAC/G,MAAI,OAAO,OAAQ,QAAO,EAAE,IAAI,OAAO,OAAO;AAC9C,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,MACL,eAAe;AAAA,MACf,UAAU;AAAA,MACV,OAAAG;AAAA,MACA,GAAI,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;AAAA,IACjD;AAAA,EACF;AACF;AAGO,SAAS,uBACd,OACA,UAA2C,CAAC,GACpB;AACxB,QAAM,SAAS,+BAA+B,OAAO,OAAO;AAC5D,MAAI,CAAC,OAAO,GAAI,OAAM,IAAI,UAAU,qCAAqC,OAAO,OAAO,KAAK,IAAI,CAAC,EAAE;AACnG,SAAO,OAAO;AAChB;;;ACpPA,IAAMC,QAAO;AACb,IAAM,cAAc;AACpB,IAAM,OAAO;AACb,IAAMC,SAAQ;AACd,IAAMC,aAAY,oBAAI,IAAI;AAAA,EACxB;AAAA,EAAiB;AAAA,EAAY;AAAA,EAAe;AAAA,EAAU;AAAA,EAAU;AAAA,EAChE;AAAA,EAAkB;AAAA,EAAe;AAAA,EAAU;AAAA,EAAc;AAAA,EAAS;AACpE,CAAC;AACD,IAAMC,aAAY,oBAAI,IAAI,CAAC,MAAM,QAAQ,aAAa,aAAa,cAAc,iBAAiB,OAAO,CAAC;AAE1G,IAAM,WAAW,CAAC,UAChB,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,IAC/D,QACA;AAEN,SAASC,aAAY,OAAgCC,UAA8B,MAAc,QAAwB;AACvH,aAAW,OAAO,OAAO,KAAK,KAAK,EAAG,KAAI,CAACA,SAAQ,IAAI,GAAG,EAAG,QAAO,KAAK,GAAG,IAAI,IAAI,GAAG,mBAAmB;AAC5G;AAEA,SAASC,MAAK,OAAgB,MAAc,QAAkB,MAAM,OAAgB;AAClF,MAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,GAAG;AAC9C,WAAO,KAAK,GAAG,IAAI,cAAc;AACjC,WAAO;AAAA,EACT;AACA,MAAI,MAAM,SAAS,IAAK,QAAO,KAAK,GAAG,IAAI,oBAAoB,GAAG,aAAa;AAC/E,SAAO,MAAM,KAAK;AACpB;AAEA,SAAS,QAAQ,OAAgB,QAAuC;AACtE,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,MAAM,QAAQ;AAC1C,WAAO,KAAK,0CAA0C;AACtD,WAAO,CAAC;AAAA,EACV;AACA,MAAI,MAAM,SAAS,GAAI,QAAO,KAAK,4CAA4C;AAC/E,QAAM,OAAO,oBAAI,IAAY;AAC7B,SAAO,MAAM,MAAM,GAAG,EAAE,EAAE,QAAQ,CAAC,KAAK,UAAU;AAChD,UAAM,OAAO,kBAAkB,KAAK;AACpC,UAAM,OAAO,SAAS,GAAG;AACzB,QAAI,CAAC,MAAM;AACT,aAAO,KAAK,GAAG,IAAI,oBAAoB;AACvC,aAAO,CAAC;AAAA,IACV;AACA,IAAAF,aAAY,MAAMD,YAAW,MAAM,MAAM;AACzC,UAAMI,MAAKD,MAAK,KAAK,IAAI,GAAG,IAAI,OAAO,QAAQ,EAAE;AACjD,QAAIC,OAAM,CAAC,KAAK,KAAKA,GAAE,EAAG,QAAO,KAAK,GAAG,IAAI,uCAAuC;AACpF,QAAI,KAAK,IAAIA,GAAE,EAAG,QAAO,KAAK,GAAG,IAAI,mBAAmBA,GAAE,GAAG;AAC7D,SAAK,IAAIA,GAAE;AACX,UAAM,OAAOD,MAAK,KAAK,MAAM,GAAG,IAAI,SAAS,QAAQ,GAAG;AACxD,QAAI,OAAO,KAAK,cAAc,UAAW,QAAO,KAAK,GAAG,IAAI,4BAA4B;AACxF,QAAI,CAAC,OAAO,UAAU,KAAK,SAAS,KAAK,OAAO,KAAK,SAAS,IAAI,EAAG,QAAO,KAAK,GAAG,IAAI,2CAA2C;AACnI,QAAI,CAAC,OAAO,UAAU,KAAK,UAAU,KAAK,OAAO,KAAK,UAAU,IAAI,KAAK,OAAO,KAAK,UAAU,IAAI,KAAa;AAC9G,aAAO,KAAK,GAAG,IAAI,sDAAsD;AAAA,IAC3E;AACA,QAAI,KAAK,kBAAkB,WAAc,OAAO,KAAK,kBAAkB,YAAY,CAACL,OAAM,KAAK,KAAK,aAAa,IAAI;AACnH,aAAO,KAAK,GAAG,IAAI,+CAA+C;AAAA,IACpE;AACA,QAAI,KAAK,cAAc,QAAQ,OAAO,KAAK,UAAU,IAAI,KAAK,CAAC,KAAK,eAAe;AACjF,aAAO,KAAK,GAAG,IAAI,uDAAuD;AAAA,IAC5E;AACA,UAAM,QAAQ,KAAK,UAAU,SAAY,SAAYK,MAAK,KAAK,OAAO,GAAG,IAAI,UAAU,QAAQ,GAAK;AACpG,WAAO,CAAC;AAAA,MACN,IAAAC;AAAA,MAAI;AAAA,MAAM,WAAW,KAAK,cAAc;AAAA,MACxC,WAAW,OAAO,KAAK,SAAS,KAAK;AAAA,MACrC,YAAY,OAAO,KAAK,UAAU,KAAK;AAAA,MACvC,GAAI,OAAO,KAAK,kBAAkB,WAAW,EAAE,eAAe,KAAK,cAAc,IAAI,CAAC;AAAA,MACtF,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IAC3B,CAAC;AAAA,EACH,CAAC;AACH;AAEA,SAAS,cAAc,OAAgB,QAAwD;AAC7F,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,QAAQ,SAAS,KAAK;AAC5B,MAAI,CAAC,OAAO;AACV,WAAO,KAAK,wCAAwC;AACpD,WAAO;AAAA,EACT;AACA,EAAAH,aAAY,OAAO,oBAAI,IAAI,CAAC,YAAY,YAAY,cAAc,MAAM,CAAC,GAAG,wBAAwB,MAAM;AAC1G,MAAI;AACF,UAAM,WAAW,mBAAmB,KAAK;AACzC,UAAM,OAAO,SAAS,MAAM,IAAI;AAChC,QAAI,MAAM,SAAS,WAAc,CAAC,QAAQ,OAAO,OAAO,IAAI,EAAE,KAAK,CAAC,SAAS,OAAO,SAAS,QAAQ,IAAI;AACvG,aAAO,KAAK,2DAA2D;AAAA,IACzE;AACA,WAAO;AAAA,MACL,UAAU,SAAS;AAAA,MACnB,UAAU,SAAS;AAAA,MACnB,GAAI,OAAO,KAAK,SAAS,UAAU,EAAE,SAAS,EAAE,YAAY,SAAS,WAAW,IAAI,CAAC;AAAA,MACrF,GAAI,OAAO,EAAE,KAAqC,IAAI,CAAC;AAAA,IACzD;AAAA,EACF,SAAS,OAAO;AACd,WAAO,KAAK,iBAAiB,QAAQ,MAAM,UAAU,iCAAiC;AACtF,WAAO;AAAA,EACT;AACF;AAEA,SAAS,SAAS,OAAgB,QAAmD;AACnF,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,QAAQ,SAAS,KAAK;AAC5B,MAAI,CAAC,OAAO;AACV,WAAO,KAAK,mCAAmC;AAC/C,WAAO;AAAA,EACT;AACA,QAAMC,WAAU,oBAAI,IAAI,CAAC,kBAAkB,oBAAoB,aAAa,kBAAkB,WAAW,CAAC;AAC1G,EAAAD,aAAY,OAAOC,UAAS,mBAAmB,MAAM;AACrD,QAAM,SAAS,CAAC;AAChB,aAAW,OAAOA,UAAS;AACzB,QAAI,MAAM,GAAG,MAAM,UAAa,QAAQ,oBAAoB,QAAQ,mBAAoB;AACxF,WAAO,GAAG,IAAIC,MAAK,MAAM,GAAG,GAAG,mBAAmB,GAAG,IAAI,MAAM;AAAA,EACjE;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAgB,QAAkD;AACjF,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,QAAQ,SAAS,KAAK;AAC5B,QAAM,SAAS,SAAS,OAAO,MAAM;AACrC,MAAI,CAAC,SAAS,CAAC,QAAQ;AACrB,WAAO,KAAK,yCAAyC;AACrD,WAAO;AAAA,EACT;AACA,EAAAF,aAAY,OAAO,oBAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,kBAAkB,MAAM;AAChE,MAAI,OAAO,KAAK,MAAM,EAAE,SAAS,IAAK,QAAO,KAAK,oDAAoD;AACtG,MAAI,mBAAmB;AACvB,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,QAAI,CAAC,iCAAiC,KAAK,GAAG,GAAG;AAC/C,aAAO,KAAK,yBAAyB,GAAG,gDAAgD;AAAA,IAC1F;AACA,UAAM,WAAW,OAAO,KAAK,EAAE,KAAK;AACpC,wBAAoB,IAAI,SAAS,SAAS,SAAS;AACnD,QAAK,OAAO,UAAU,YAAY,OAAO,UAAU,YAC9C,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,KACpD,CAAC,YAAY,SAAS,SAAS,OAC/B,sFAAsF,KAAK,QAAQ,GAAG;AACxG,aAAO,KAAK,yBAAyB,GAAG,4CAA4C;AAAA,IACtF;AAAA,EACF;AACA,MAAI,mBAAmB,MAAQ,QAAO,KAAK,yDAAyD;AACpG,SAAO,EAAE,OAAkD;AAC7D;AAGO,SAAS,8BAA8B,OAAyC;AACrF,QAAM,SAAmB,CAAC;AAC1B,QAAM,OAAO,SAAS,KAAK;AAC3B,MAAI,CAAC,KAAM,QAAO,EAAE,IAAI,OAAO,QAAQ,CAAC,4BAA4B,EAAE;AACtE,EAAAA,aAAY,MAAMF,YAAW,YAAY,MAAM;AAC/C,MAAI,KAAK,kBAAkB,EAAG,QAAO,KAAK,kCAAkC;AAC5E,MAAI,CAAC,OAAO,cAAc,KAAK,QAAQ,KAAK,OAAO,KAAK,QAAQ,IAAI,EAAG,QAAO,KAAK,8CAA8C;AACjI,MAAI,CAAC,OAAO,cAAc,KAAK,WAAW,KAAK,OAAO,KAAK,WAAW,IAAI,EAAG,QAAO,KAAK,iDAAiD;AAC1I,QAAM,SAAS,SAAS,KAAK,MAAM;AACnC,QAAM,SAAS,SAAS,KAAK,MAAM;AACnC,QAAM,QAAQI,MAAK,QAAQ,OAAO,yBAAyB,QAAQ,EAAE;AACrE,QAAM,YAAYA,MAAK,QAAQ,WAAW,6BAA6B,QAAQ,EAAE;AACjF,QAAM,cAAcA,MAAK,QAAQ,aAAa,+BAA+B,QAAQ,EAAE;AACvF,MAAI,SAAS,CAACN,MAAK,KAAK,KAAK,EAAG,QAAO,KAAK,oDAAoD;AAChG,MAAI,aAAa,CAACA,MAAK,KAAK,SAAS,EAAG,QAAO,KAAK,wDAAwD;AAC5G,MAAI,eAAe,CAAC,YAAY,KAAK,WAAW,EAAG,QAAO,KAAK,wCAAwC;AACvG,MAAI,QAAQ,eAAe,UAAU,QAAQ,eAAe,OAAQ,QAAO,KAAK,iDAAiD;AACjI,QAAMQ,SAAQ,QAAQ,KAAK,OAAO,MAAM;AACxC,QAAM,YAAYA,OAAM,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AACjG,QAAM,OAAO,+BAA+B,KAAK,gBAAgB,EAAE,OAAO,UAAU,CAAC;AACrF,MAAI,CAAC,KAAK,GAAI,QAAO,KAAK,GAAG,KAAK,MAAM;AAAA,WAC/B,KAAK,MAAM,MAAM,KAAK,CAAC,MAAM,UAAU,KAAK,WAAW,UAAU,KAAK,GAAG,EAAE,GAAG;AACrF,WAAO,KAAK,4EAA4E;AAAA,EAC1F;AACA,QAAM,cAAc,cAAc,KAAK,aAAa,MAAM;AAC1D,QAAM,SAAS,SAAS,KAAK,QAAQ,MAAM;AAC3C,MAAI;AACJ,MAAI,KAAK,eAAe,QAAW;AACjC,UAAM,UAAU,mBAAmB,KAAK,UAAmB;AAC3D,QAAI,CAAC,QAAQ,GAAI,QAAO,KAAK,GAAG,OAAO,QAAQ,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,uBAAuB,GAAG,KAAK,KAAK,EAAE,CAAC;AAAA,QACvH,cAAa,KAAK;AAAA,EACzB;AACA,QAAM,QAAQ,QAAQ,KAAK,OAAO,MAAM;AACxC,QAAM,aAAa,KAAK,eAAe,SACnC,SACA,yBAAyB,KAAK,YAAY,IAAI,IAAIA,OAAM,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC;AACnF,MAAI,cAAc,CAAC,WAAW,GAAI,QAAO,KAAK,GAAG,WAAW,MAAM;AAClE,MAAI,OAAO,UAAU,CAAC,KAAK,GAAI,QAAO,EAAE,IAAI,OAAO,OAAO;AAC1D,SAAO,EAAE,IAAI,MAAM,OAAO;AAAA,IACxB,eAAe;AAAA,IACf,UAAU,OAAO,KAAK,QAAQ;AAAA,IAC9B,aAAa,OAAO,KAAK,WAAW;AAAA,IACpC,QAAQ,EAAE,MAAM;AAAA,IAChB,QAAQ,EAAE,WAAW,aAAa,YAAY,QAAQ,WAA8B;AAAA,IACpF,OAAAA;AAAA,IACA,gBAAgB,KAAK;AAAA,IACrB,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,IACrC,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,IACnC,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IACzB,GAAI,YAAY,KAAK,EAAE,YAAY,WAAW,MAAM,IAAI,CAAC;AAAA,EAC3D,EAAE;AACJ;;;AC5MO,IAAM,8BAA8B;AAEpC,IAAM,gCAAgC;AAE7C,IAAM,aAAa;AACnB,IAAM,SAAS;AACf,IAAM,eAAe;AACrB,IAAM,aAAa;AACnB,IAAM,mBAAmB;AACzB,IAAM,wBAAwB;AAuC9B,SAAS,gBACP,OACkC;AAClC,QAAM,UAAU,OAAO,QAAQ,SAAS,CAAC,CAAC;AAC1C,MAAI,QAAQ,SAAS,YAAY;AAC/B,UAAM,IAAI,UAAU,yCAAyC,UAAU,SAAS;AAAA,EAClF;AACA,QAAM,SAAiC,CAAC;AACxC,MAAI,mBAAmB;AACvB,aAAW,CAAC,MAAM,GAAG,KAAK,QAAQ,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,MAAM,KAAK,cAAc,KAAK,CAAC,GAAG;AACtF,QAAI,CAAC,WAAW,KAAK,IAAI,GAAG;AAC1B,YAAM,IAAI,UAAU,+BAA+B,IAAI,0CAA0C;AAAA,IACnG;AACA,QAAK,OAAO,QAAQ,YAAY,OAAO,QAAQ,YAC1C,OAAO,QAAQ,YAAY,CAAC,OAAO,SAAS,GAAG,GAAI;AACtD,YAAM,IAAI,UAAU,+BAA+B,IAAI,qCAAqC;AAAA,IAC9F;AACA,UAAM,QAAQ,OAAO,GAAG,EAAE,KAAK;AAC/B,QAAI,CAAC,SAAS,MAAM,SAAS,oBAAoB,aAAa,KAAK,KAAK,GAAG;AACzE,YAAM,IAAI,UAAU,+BAA+B,IAAI,oCAAoC;AAAA,IAC7F;AACA,wBAAoB,KAAK,SAAS,MAAM,SAAS;AACjD,QAAI,mBAAmB,uBAAuB;AAC5C,YAAM,IAAI,UAAU,wDAAwD;AAAA,IAC9E;AACA,WAAO,IAAI,IAAI;AAAA,EACjB;AACA,SAAO;AACT;AAEA,SAAS,OAAO,QAAkD;AAChE,QAAM,eAAe,OAAO,QAAQ,MAAM,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,KAAK,IAAI,KAAK,KAAK,GAAG;AACzF,SAAO,aAAa,SAAS;AAAA,EAAY,aAAa,KAAK,IAAI,CAAC;AAAA,KAAQ;AAC1E;AAEA,SAAS,SACP,UACA,SACuD;AACvD,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,MACL,KAAK,OAAO,gBAAgB,QAAQ,eAAe,CAAC;AAAA,MACpD,UAAU,EAAE,QAAQ,aAAa,UAAU,MAAM,QAAQ,MAAM,UAAU,2BAA2B;AAAA,IACtG;AAAA,EACF;AACA,MAAI,CAAC,OAAO,cAAc,SAAS,QAAQ,KAAK,SAAS,WAAW,KAAK,CAAC,OAAO,KAAK,SAAS,MAAM,GAAG;AACtG,UAAM,IAAI,UAAU,mDAAmD;AAAA,EACzE;AACA,SAAO;AAAA,IACL,KAAK,OAAO,gBAAgB,SAAS,OAAO,MAAM,CAAC;AAAA,IACnD,UAAU;AAAA,MACR,QAAQ;AAAA,MACR,UAAU,SAAS;AAAA,MACnB,QAAQ,SAAS;AAAA,MACjB,UAAU,kBAAkB,SAAS,MAAM;AAAA,IAC7C;AAAA,EACF;AACF;AAEA,SAAS,WAAW,UAA8C;AAChE,SAAO;AAAA,IACL,OAAO,6BAA6B;AAAA,IACpC,+BAA+B,SAAS,MAAM;AAAA,IAC9C,kCAAkC,SAAS,QAAQ;AAAA,IACnD,GAAI,SAAS,aAAa,OAAO,CAAC,IAAI,CAAC,iCAAiC,SAAS,QAAQ,GAAG;AAAA,IAC5F,GAAI,SAAS,WAAW,OAAO,CAAC,IAAI,CAAC,+BAA+B,SAAS,MAAM,GAAG;AAAA,EACxF,EAAE,KAAK,GAAG;AACZ;AAMO,SAAS,6BACd,UACA,UAAqC,CAAC,GACd;AACxB,QAAM,EAAE,KAAK,SAAS,IAAI,SAAS,UAAU,OAAO;AACpD,SAAO,EAAE,KAAK,UAAU,MAAM,UAAU,WAAW,QAAQ,CAAC,IAAI,GAAG,WAAW;AAChF;AAMO,SAAS,6BACd,MACA,UACA,SAAiB,6BACT;AACR,QAAM,WAAW;AACjB,QAAM,iBAAiB,KAAK,MAAM,QAAQ,KAAK,CAAC;AAChD,MAAI,eAAe,SAAS,GAAG;AAC7B,UAAM,IAAI,UAAU,2DAA2D;AAAA,EACjF;AACA,MAAI,eAAe,WAAW,EAAG,QAAO,KAAK,QAAQ,UAAU,SAAS,IAAI;AAC5E,QAAM,cAAc,KAAK,QAAQ,MAAM;AACvC,MAAI,eAAe,GAAG;AACpB,QAAI,KAAK,QAAQ,QAAQ,cAAc,OAAO,MAAM,KAAK,GAAG;AAC1D,YAAM,IAAI,UAAU,sDAAsD;AAAA,IAC5E;AACA,WAAO,GAAG,KAAK,MAAM,GAAG,WAAW,CAAC,GAAG,SAAS,IAAI,GAAG,KAAK,MAAM,cAAc,OAAO,MAAM,CAAC;AAAA,EAChG;AACA,QAAM,cAAc,KAAK,OAAO,cAAc;AAC9C,MAAI,cAAc,EAAG,OAAM,IAAI,UAAU,4CAA4C;AACrF,SAAO,GAAG,KAAK,MAAM,GAAG,WAAW,CAAC,GAAG,SAAS,IAAI,GAAG,KAAK,MAAM,WAAW,CAAC;AAChF;AAOO,SAAS,0BACd,QACA,UACA,UAAqC,CAAC,GAC7B;AACT,QAAM,OAAO,SAAS,UAAU,OAAO;AACvC,QAAM,gBAAgB,OAAO,aAAa,4BAA4B;AACtE,QAAM,kBAAkB,OAAO,aAAa,8BAA8B;AAC1E,QAAM,gBAAgB,OAAO,aAAa,4BAA4B;AACtE,MAAI,kBAAkB,KAAK,SAAS,UAChC,qBAAqB,KAAK,SAAS,aAAa,OAAO,OAAO,OAAO,KAAK,SAAS,QAAQ,MAC3F,kBAAkB,KAAK,SAAS,QAAQ;AAC1C,WAAO;AAAA,EACT;AACA,SAAO,cAAc,KAAK;AAC1B,SAAO,aAAa,8BAA8B,KAAK,SAAS,MAAM;AACtE,SAAO,aAAa,iCAAiC,KAAK,SAAS,QAAQ;AAC3E,MAAI,KAAK,SAAS,aAAa,KAAM,QAAO,gBAAgB,8BAA8B;AAAA,MACrF,QAAO,aAAa,gCAAgC,OAAO,KAAK,SAAS,QAAQ,CAAC;AACvF,MAAI,KAAK,SAAS,WAAW,KAAM,QAAO,gBAAgB,4BAA4B;AAAA,MACjF,QAAO,aAAa,8BAA8B,KAAK,SAAS,MAAM;AAC3E,SAAO;AACT;;;ACnLA,IAAMC,gBAAe;AACrB,IAAMC,gBAAe;AACrB,IAAMC,aAAY;AAClB,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAIzB,SAAS,gBAAgB,YAAoF;AAC3G,QAAM,UAAU,WAAW,KAAK;AAChC,QAAM,aAAa,QAAQ,YAAY;AACvC,MAAI,eAAe,UAAW,QAAO,EAAE,SAAS,UAAU;AAC1D,MAAI,eAAe,WAAY,QAAO,EAAE,SAAS,WAAW;AAC5D,MAAI,eAAe,gBAAgB,eAAe,YAAa,QAAO,EAAE,SAAS,YAAY;AAC7F,MAAI,eAAe,YAAY,eAAe,iBAAkB,QAAO,EAAE,SAAS,SAAS;AAC3F,QAAM,UAAU,QAAQ,MAAM,gCAAgC;AAC9D,MAAI,QAAS,QAAO,EAAE,SAAS,WAAW,GAAI,QAAQ,CAAC,GAAG,KAAK,IAAI,EAAE,cAAc,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,EAAG;AAC7G,SAAO,CAAC;AACV;AAEA,SAAS,iBAAiB,OAA0B,MAAc,QAA4B;AAC5F,QAAM,WAAqB,CAAC;AAC5B,aAAW,CAAC,OAAO,IAAI,KAAK,MAAM,QAAQ,GAAG;AAC3C,QAAI,CAAC,KAAK,KAAK,EAAG;AAClB,UAAM,QAAQ,KAAK,MAAM,gBAAgB;AACzC,QAAI,CAAC,OAAO;AACV,aAAO,KAAK,GAAG,IAAI,SAAS,QAAQ,CAAC,4BAA4B;AACjE;AAAA,IACF;AACA,UAAMC,SAAQ,MAAM,CAAC,KAAK,IAAI,KAAK;AACnC,QAAIA,MAAK,SAAS,IAAO,QAAO,KAAK,GAAG,IAAI,SAAS,QAAQ,CAAC,mCAAmC;AACjG,QAAIA,MAAM,UAAS,KAAKA,KAAI;AAAA,EAC9B;AACA,MAAI,SAAS,SAASH,cAAc,QAAO,KAAK,GAAG,IAAI,qBAAqBA,aAAY,UAAU;AAClG,SAAO,SAAS,MAAM,GAAGA,aAAY;AACvC;AAaO,SAAS,4BACd,cACA,QAC8B;AAC9B,MAAI,OAAO,WAAW,SAAU,QAAO,EAAE,IAAI,OAAO,QAAQ,CAAC,sCAAsC,EAAE;AACrG,MAAI,OAAO,SAASC,eAAc;AAChC,WAAO,EAAE,IAAI,OAAO,QAAQ,CAAC,uCAAuCA,cAAa,eAAe,OAAO,CAAC,aAAa,EAAE;AAAA,EACzH;AACA,MAAI,CAAC,OAAO,KAAK,EAAG,QAAO,EAAE,IAAI,MAAM,OAAO,EAAE,GAAG,aAAa,EAAE;AAElE,QAAM,SAAmB,CAAC;AAC1B,QAAM,WAAW,oBAAI,IAA2E;AAChG,QAAM,UAAoB,CAAC;AAC3B,MAAI,UAA4C;AAChD,aAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,UAAU,IAAI,EAAE,MAAM,IAAI,EAAE,QAAQ,GAAG;AAChF,UAAM,UAAU,KAAK,MAAM,gBAAgB;AAC3C,QAAI,SAAS;AACX,YAAM,cAAc,QAAQ,CAAC,KAAK;AAClC,YAAM,SAAS,gBAAgB,WAAW;AAC1C,UAAI,CAAC,OAAO,SAAS;AACnB,eAAO,KAAK,gCAAgC,YAAY,KAAK,CAAC,oBAAoB;AAClF,kBAAU;AACV;AAAA,MACF;AACA,UAAI,SAAS,IAAI,OAAO,OAAO,GAAG;AAChC,eAAO,KAAK,mCAAmC,OAAO,OAAO,UAAU;AACvE,kBAAU,OAAO;AACjB;AAAA,MACF;AACA,eAAS,IAAI,OAAO,SAAS,EAAE,OAAO,CAAC,GAAG,GAAI,OAAO,eAAe,EAAE,cAAc,OAAO,aAAa,IAAI,CAAC,EAAG,CAAC;AACjH,gBAAU,OAAO;AACjB;AAAA,IACF;AACA,QAAI,iBAAiB,KAAK,IAAI,GAAG;AAC/B,aAAO,KAAK,4BAA4B,QAAQ,CAAC,8BAA8B;AAC/E;AAAA,IACF;AACA,QAAI,QAAS,UAAS,IAAI,OAAO,GAAG,MAAM,KAAK,IAAI;AAAA,QAC9C,SAAQ,KAAK,IAAI;AAAA,EACxB;AAEA,QAAM,kBAA4B,CAAC;AACnC,QAAM,iBAA2B,CAAC;AAClC,aAAW,QAAQ,SAAS;AAC1B,UAAM,UAAU,KAAK,MAAM,gBAAgB;AAC3C,QAAI,QAAS,iBAAgB,MAAM,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAC;AAAA,QACtD,gBAAe,KAAK,IAAI;AAAA,EAC/B;AACA,MAAI,gBAAgB,SAASD,cAAc,QAAO,KAAK,gDAAgDA,aAAY,WAAW;AAC9H,MAAI,gBAAgB,KAAK,CAAC,YAAY,QAAQ,SAAS,GAAK,EAAG,QAAO,KAAK,+DAA+D;AAE1I,QAAM,iBAAiB,SAAS,IAAI,SAAS;AAC7C,QAAM,kBAAkB,SAAS,IAAI,UAAU;AAC/C,QAAM,mBAAmB,SAAS,IAAI,WAAW;AACjD,QAAM,iBAAiB,SAAS,IAAI,SAAS;AAC7C,QAAM,gBAAgB,SAAS,IAAI,QAAQ;AAC3C,QAAM,mBAAmB,gBAAgB,SAAS,gBAAgB,KAAK,IAAI,EAAE,KAAK;AAClF,QAAM,WAAW,kBACb,iBAAiB,gBAAgB,OAAO,gCAAgC,MAAM,IAC9E,gBAAgB,OAAO,OAAO,EAAE,MAAM,GAAGA,aAAY;AACzD,QAAM,oBAAoB,kBAAkB,MAAM,KAAK,IAAI,EAAE,KAAK;AAClE,QAAM,cAAc,gBAAgB,MAAM,KAAK,IAAI,EAAE,KAAK;AAC1D,QAAM,cAAc,eAAe,MAAM,OAAO,CAAC,SAAS,KAAK,KAAK,CAAC;AACrE,QAAM,WAAW,aAAa,KAAK,GAAG,EAAE,KAAK;AAC7C,MAAI,eAAe,YAAY,WAAW,EAAG,QAAO,KAAK,0DAA0D;AACnH,MAAI,YAAY,SAAS,SAASE,WAAW,QAAO,KAAK,8CAA8CA,UAAS,aAAa;AAC7H,MAAI,kBAAkB,CAAC,YAAa,QAAO,KAAK,oDAAoD;AACpG,MAAI,gBAAgB,gBAAgB,eAAe,aAAa,SAASA,YAAW;AAClF,WAAO,KAAK,qDAAqDA,UAAS,aAAa;AAAA,EACzF;AACA,MAAI,OAAO,OAAQ,QAAO,EAAE,IAAI,OAAO,OAAO;AAE9C,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,OAAO;AAAA,MACL,GAAG;AAAA,MACH,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,MAC7C,GAAI,mBAAmB,gBAAgB,SAAS,EAAE,SAAS,IAAI,CAAC;AAAA,MAChE,GAAI,mBAAmB,EAAE,mBAAmB,qBAAqB,GAAG,IAAI,CAAC;AAAA,MACzE,GAAI,iBAAiB;AAAA,QACnB,SAAS;AAAA,UACP,GAAI,eAAe,gBAAgB,aAAa,SAAS,QACrD,EAAE,OAAO,eAAe,gBAAgB,aAAa,SAAS,MAAM,IACpE,CAAC;AAAA,UACL,cAAc,eAAe;AAAA,QAC/B;AAAA,MACF,IAAI,CAAC;AAAA,MACL,GAAI,iBAAiB,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IAClD;AAAA,EACF;AACF;AAGO,SAAS,uCACd,cACA,QAC4B;AAC5B,QAAM,SAAS,4BAA4B,cAAc,MAAM;AAC/D,MAAI,CAAC,OAAO,GAAI,OAAM,IAAI,UAAU,gCAAgC,OAAO,OAAO,KAAK,IAAI,CAAC,EAAE;AAC9F,SAAO,OAAO;AAChB;;;AC5JA;AAAA,EACE;AAAA,OAIK;AAMA,IAAM,4BAA4B;AAQzC,IAAM,aAAa,CAAC,WAAmB,gBAAgD;AAAA,EACrF;AAAA,IACE,MAAM;AAAA,IAAqB,IAAI;AAAA,IAAW,QAAQ;AAAA,IAClD,OAAO;AAAA,MACL,GAAG,YAAY,IAAI,CAACE,QAAO,SAASA,GAAE,iBAAiB;AAAA,MACvD;AAAA,MAA+B;AAAA,MAC/B;AAAA,MAAqC;AAAA,IACvC;AAAA,IACA,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IAAmB,IAAI;AAAA,IAAW,QAAQ;AAAA,IAChD,OAAO,CAAC,kBAAkB,cAAc,cAAc,SAAS;AAAA,IAC/D,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IAAkB,IAAI;AAAA,IAAW,QAAQ;AAAA,IAC/C,OAAO,CAAC,YAAY,iBAAiB,gBAAgB;AAAA,IACrD,QAAQ;AAAA,EACV;AAAA,EACA;AAAA,IACE,MAAM;AAAA,IAAmB,IAAI;AAAA,IAAW,QAAQ;AAAA,IAChD,OAAO,CAAC,gCAAgC,sBAAsB,4BAA4B;AAAA,IAC1F,QAAQ;AAAA,EACV;AACF;AAGA,eAAsB,uBAAuB,OAA+D;AAC1G,MAAI,CAAC,wBAAwB,KAAK,MAAM,MAAM,EAAG,OAAM,IAAI,UAAU,qCAAqC;AAC1G,QAAM,UAAU,8BAA8B,MAAM,QAAQ;AAC5D,MAAI,CAAC,QAAQ,GAAI,OAAM,IAAI,UAAU,QAAQ,OAAO,KAAK,IAAI,CAAC;AAC9D,QAAM,WAAW,QAAQ;AACzB,MAAI,MAAM,oBAAoB,QAAQ,MAAM,MAAM,OAAQ,OAAM,IAAI,UAAU,sDAAsD;AACpI,QAAM,WAAW,WAAW,SAAS,OAAO,SAAS,IAAI,SAAS,QAAQ;AAC1E,QAAM,sBAAsB;AAAA,IAC1B,SAAS;AAAA,IACT,WAAW,CAAC,kBAAkB,SAAS,QAAQ,IAAI,SAAS,OAAO,OAAO,SAAS,OAAO,SAAS,EAAE,KAAK;AAAA,IAC1G,gBAAgB,CAAC,MAAM,MAA4B;AAAA,EACrD;AACA,QAAM,WAAW,CAAC,MAAcA,KAAY,aAA8C;AAAA,IACxF;AAAA,IAAM,IAAAA;AAAA,IAAI,gBAAgB;AAAA,IAAU,YAAY;AAAA,IAChD,SAAS,wBAAwB,OAAO;AAAA,EAC1C;AACA,QAAM,YAAY,SAAS,OAAO;AAClC,QAAM,YAAY;AAAA,IAChB,SAAS,mBAAmB,WAAW;AAAA,MACrC;AAAA,MACA,OAAO,SAAS,MAAM,IAAI,CAAC,EAAE,eAAe,aAAa,GAAG,KAAK,MAAM,IAAI;AAAA,IAC7E,CAAC;AAAA,IACD,SAAS,2BAA2B,WAAW,SAAS,cAAc;AAAA,IACtE,GAAI,SAAS,cAAc,CAAC,SAAS,uBAAuB,WAAW,SAAS,WAAW,CAAC,IAAI,CAAC;AAAA,IACjG,GAAI,SAAS,SAAS,CAAC,SAAS,kBAAkB,WAAW,SAAS,MAAM,CAAC,IAAI,CAAC;AAAA,IAClF,GAAI,SAAS,aAAa,CAAC,SAAS,sBAAsB,WAAW,SAAS,UAAU,CAAC,IAAI,CAAC;AAAA,IAC9F,GAAI,SAAS,QAAQ,CAAC,SAAS,iBAAiB,WAAW,SAAS,KAAK,CAAC,IAAI,CAAC;AAAA,EACjF;AACA,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA,YAAY,WAAW,WAAW,SAAS,MAAM,OAAO,CAAC,SAAS,KAAK,aAAa,EAAE,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC;AAAA,IAC5G,eAAe;AAAA,MACb;AAAA,QACE,MAAM;AAAA,QAAiC,MAAM;AAAA,QAAgD,UAAU,SAAS;AAAA,QAChH,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,MAAM;AAAA,QAAoB,MAAM;AAAA,QAAa,UAAU;AAAA,QACvD,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;","names":["allowed","id","paymentsReady","tiers","attr","attr","id","attr","id","superAdmins","id","text","DEFAULT_REQUIRED","DEFAULT_OPTIONAL","SLUG","SLUG","SECRET_NAME","SLUG","id","rows","tiers","SLUG","allowed","tiers","id","SLUG","value","tiers","record","text","emailLog","id","str","encoder","canonicalValue","record","ID","EMAIL_RE","id","ID","record","allowed","id","record","createRecord","updateRecord","updateRecord","createRecord","verifyStripeSignature","id","id","record","meetings","rows","ROOT_KEYS","MAX_MARKDOWN","allowed","text","tiers","SLUG","PRICE","ROOT_KEYS","TIER_KEYS","unknownKeys","allowed","text","id","tiers","MAX_BENEFITS","MAX_MARKDOWN","MAX_LABEL","text","id"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/member.ts","../src/application-id.ts","../src/email-identity.ts","../src/schema-applications.ts","../src/schema-admission.ts","../src/schema-gifts.ts","../src/schema.ts","../src/defaults.ts","../src/group.ts","../src/auth.ts","../src/pipeline.ts","../src/copy-defaults-admin.ts","../src/copy-defaults.ts","../src/copy-resolve.ts","../src/flow-fields.ts","../src/formation.ts","../src/config-network.ts","../src/config-signup-control.ts","../src/config-member-content.ts","../src/leader.ts","../src/descriptor.ts","../src/tiers.ts","../src/member-content-validation-helpers.ts","../src/member-content-validation.ts","../src/member-content.ts","../src/member-content-canonical.ts","../src/email.ts","../src/notify.ts","../src/payments.ts","../src/admission-grants-contract.ts","../src/signup-control-canonical.ts","../src/admission-grants.ts","../src/join-continuation.ts","../src/gift-offers.ts","../src/network.ts","../src/network-contract.ts","../src/crm-sync.ts","../src/series.ts","../src/payments-stripe.ts","../src/clerk.ts","../src/clerk-roles.ts","../src/clerk-integration.ts","../src/session.ts","../src/brand.ts","../src/reconcile.ts","../src/scheduling.ts","../src/tiers-store.ts","../src/signup-control-contract.ts","../src/membership-page.ts","../src/signup-control-validate.ts","../src/signup-control-theme.ts","../src/membership-markdown.ts","../src/promotion.ts"],"sourcesContent":["// defineChapter — validate-at-import config, reusing @odla-ai/crm's defineCrm.\n// A bad config throws here (startup), never at request time.\nimport { defineCrm } from \"@odla-ai/crm\";\nimport type { CrmConfig, Crm } from \"@odla-ai/crm\";\nimport type {\n Chapter,\n ChapterConfig,\n ChapterMode,\n ResolvedOperations,\n} from \"./types\";\nimport { chapterDb } from \"./schema\";\nimport { defaultCrm } from \"./defaults\";\nimport { buildGroupSeed } from \"./group\";\nimport { resolveAuth } from \"./auth\";\nimport { resolvePipeline } from \"./pipeline\";\nimport { resolveApplication } from \"./member\";\nimport { resolveChapterCopy } from \"./copy\";\nimport { resolveLeaderFormation } from \"./formation\";\nimport { resolveNetwork } from \"./config-network\";\nimport { resolveSignupControl } from \"./config-signup-control\";\nimport { resolveMemberContent } from \"./config-member-content\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\n\nfunction isResolvedCrm(x: CrmConfig | Crm | undefined): x is Crm {\n return (\n !!x &&\n typeof x === \"object\" &&\n \"prepare\" in x &&\n typeof (x as { prepare?: unknown }).prepare === \"function\"\n );\n}\n\n/**\n * Validate a chapter/hub config and resolve its engine — the CRM, the chapter's\n * odla-db schema/rules, and the seed groups row. Throws at import on a bad\n * config (bad slug, wrong mode, missing chapter-mode prices/emails), never at\n * request time.\n */\nexport function defineChapter(config: ChapterConfig): Chapter {\n if (!config || typeof config !== \"object\") throw new Error(\"defineChapter: a config object is required\");\n const { id, name } = config;\n if (typeof id !== \"string\" || !SLUG.test(id)) {\n throw new Error(`defineChapter.id: must be a lowercase slug [a-z0-9-] (2-63 chars) — got ${JSON.stringify(id)}`);\n }\n if (typeof name !== \"string\" || name.trim() === \"\") throw new Error(\"defineChapter.name: a non-empty name is required\");\n\n const mode: ChapterMode = config.mode ?? \"chapter\";\n if (mode !== \"chapter\" && mode !== \"hub\") throw new Error(`defineChapter.mode: must be \"chapter\" or \"hub\" — got ${JSON.stringify(config.mode)}`);\n\n const crm: Crm = isResolvedCrm(config.crm) ? config.crm : defineCrm(config.crm ?? defaultCrm(mode));\n\n if (mode === \"chapter\") {\n if (!config.emails || typeof config.emails.notificationEmail !== \"string\" || config.emails.notificationEmail === \"\") {\n throw new Error(\"defineChapter.emails.notificationEmail: required in chapter mode\");\n }\n if (!config.prices || typeof config.prices.standardCents !== \"number\") {\n throw new Error(\"defineChapter.prices.standardCents: required in chapter mode\");\n }\n if (config.account === undefined) {\n throw new Error('defineChapter.account: required in chapter mode; choose \"none\", \"create\", or \"invite\" explicitly');\n }\n }\n\n const auth = resolveAuth(mode, config.auth);\n const pipeline = resolvePipeline(config.pipeline);\n const application = resolveApplication(config.application);\n const brand = { ...config.brand, wordmark: config.brand?.wordmark ?? name };\n const copy = resolveChapterCopy(config.copy);\n const network = resolveNetwork(config, crm);\n const signupControl = resolveSignupControl(config.signupControl);\n const memberContent = resolveMemberContent(config.memberContent);\n const formation = resolveLeaderFormation(config.formation, crm);\n if (signupControl && mode !== \"chapter\") {\n throw new Error(\"defineChapter.signupControl: only chapter-mode followers can receive signup control\");\n }\n if (memberContent && mode !== \"chapter\") {\n throw new Error(\"defineChapter.memberContent: only chapter-mode sites can serve member content\");\n }\n const { schema, rules } = chapterDb(\n mode, auth, network.targets.length > 0, application, Boolean(signupControl), Boolean(memberContent),\n );\n const services = config.services ?? [\"db\", \"calendar\", \"o11y\"];\n // Hub mode has no public application flow, so its inert resolved value remains\n // `none`. Chapter mode was required to make this decision above.\n const account = config.account ?? \"none\";\n if (account !== \"invite\" && account !== \"create\" && account !== \"none\") {\n throw new Error(`defineChapter.account: must be \"invite\", \"create\", or \"none\" — got \"${String(account)}\"`);\n }\n // crmFields not declared on the CRM person type are dropped by the projection at\n // runtime (the base person still lands), so a typo is invisible. Both the\n // resolved crmFields and the resolved crm are in hand here — cross-check the\n // names and fail at resolve time instead.\n if (application.crmFields.length > 0) {\n let personFields: string[] | null = null;\n try {\n personFields = Object.keys(crm.type(\"person\").fields ?? {});\n } catch {\n // No introspectable \"person\" type — leave it to the projection.\n }\n const unknown = personFields ? application.crmFields.filter((f) => !personFields.includes(f)) : [];\n if (unknown.length > 0) {\n throw new Error(\n `defineChapter.application.crmFields: ${unknown.map((f) => `\"${f}\"`).join(\", \")} not declared on the CRM \"person\" type ` +\n `(declared: ${personFields?.join(\", \")}). An undeclared field is silently dropped from the CRM projection — ` +\n `add it to your crm config's person fields, or remove it from crmFields.`,\n );\n }\n }\n const adminNotification = config.sends?.adminNotification ?? \"submit\";\n if (adminNotification !== \"submit\" && adminNotification !== \"payment\" && adminNotification !== \"never\") {\n throw new Error(\n `defineChapter.sends.adminNotification: must be \"submit\", \"payment\", or \"never\" — got \"${String(adminNotification)}\"`,\n );\n }\n const sends = { adminNotification };\n\n // Admin-operation policy. The escalation RULES are not here — they are\n // package-enforced in canChangeRole (gated on auth.superAdmins), so a site\n // cannot weaken them. These two are genuine per-site decisions.\n const onApproveCfg = config.operations?.onApprove ?? {};\n // Default promotion target: the rung directly below admin, so a custom ladder\n // gets the right answer instead of a hardcoded \"member\".\n const belowAdmin = auth.ladder[auth.ladder.length - 2] ?? auth.adminRole;\n const promoteTo = onApproveCfg.promoteTo === undefined ? belowAdmin : onApproveCfg.promoteTo;\n if (promoteTo !== false && !auth.ladder.includes(promoteTo)) {\n throw new Error(\n `defineChapter.operations.onApprove.promoteTo: \"${String(promoteTo)}\" is not in the auth ladder (${auth.ladder.join(\", \")})`,\n );\n }\n const refundCfg = config.operations?.refund ?? {};\n if (refundCfg.allowedFrom !== undefined) {\n const unknown = refundCfg.allowedFrom.filter((s) => !pipeline.stages.includes(s));\n if (unknown.length > 0) {\n throw new Error(\n `defineChapter.operations.refund.allowedFrom: ${unknown.map((s) => `\"${s}\"`).join(\", \")} not in the pipeline (${pipeline.stages.join(\", \")})`,\n );\n }\n }\n const operations: ResolvedOperations = {\n onApprove: { promoteTo, send: onApproveCfg.send === undefined ? \"onboardingInvite\" : onApproveCfg.send },\n refund: { allowedFrom: refundCfg.allowedFrom ?? null, cancelSubscription: refundCfg.cancelSubscription ?? true },\n };\n\n const chapter: Chapter = {\n config,\n id,\n name,\n mode,\n brand,\n copy,\n network,\n signupControl,\n memberContent,\n formation,\n crm,\n auth,\n pipeline,\n application,\n schema,\n rules,\n services,\n account,\n sends,\n operations,\n groupSeed: () => (mode === \"chapter\" ? buildGroupSeed(config) : null),\n };\n if (config.url !== undefined) chapter.url = config.url;\n return chapter;\n}\n","// The public member surface logic: the join config a site's join page reads (B1)\n// and the idempotent application submit (B2 validation + B3 exactly-once). Both\n// take the structural ChapterDb, so they're tested against an in-memory fake and\n// carry no runtime @odla-ai/db import. The worker builds the real db client, does\n// Clerk verification, enforces the body cap, and mounts these on chapter routes.\nimport type { Chapter, ChapterApplication, ChapterDb, ResolvedApplication } from \"./types\";\nimport { assertFieldCondition, resolveFieldStates } from \"@odla-ai/crm\";\nimport type { FieldConditions } from \"@odla-ai/crm\";\nimport { applicationIdForSubmission } from \"./application-id\";\nimport type { JoinConfigTier } from \"./tiers\";\nimport type { AdmissionGrantRow } from \"./admission-grants\";\nimport { normalizeChapterEmail } from \"./email-identity\";\n\n// The reference join form. `focus` (a json field) is always accepted.\nconst DEFAULT_REQUIRED = [\"firstName\", \"lastName\", \"email\", \"referral\", \"whoYouAre\", \"message\"];\nconst DEFAULT_OPTIONAL = [\"referralName\", \"linkedin\", \"phone\", \"state\"];\nconst SCHEMA_FIELD = /^[A-Za-z_][A-Za-z0-9_-]*$/;\n\n/** Apply defaults + validate the application config. Throws at import on bad shape. */\nexport function resolveApplication(a: ChapterApplication | undefined): ResolvedApplication {\n const required = a?.required ?? DEFAULT_REQUIRED;\n const optional = a?.optional ?? DEFAULT_OPTIONAL;\n for (const [name, arr] of [[\"required\", required], [\"optional\", optional]] as const) {\n if (!Array.isArray(arr) || !arr.every((f) => typeof f === \"string\" && f !== \"\")) {\n throw new Error(`defineChapter.application.${name}: must be an array of field-name strings`);\n }\n const unsafe = arr.find((field) => !SCHEMA_FIELD.test(field));\n if (unsafe) {\n throw new Error(`defineChapter.application.${name}: field \"${unsafe}\" must match ${SCHEMA_FIELD.source}`);\n }\n }\n const duplicate = [...required, ...optional].find((field, index, fields) => fields.indexOf(field) !== index);\n if (duplicate) {\n throw new Error(`defineChapter.application: duplicate field \"${duplicate}\" across required/optional lists`);\n }\n if (a?.profileFields !== undefined && (!Array.isArray(a.profileFields) || !a.profileFields.every((f) => typeof f === \"string\" && f !== \"\"))) {\n throw new Error(\"defineChapter.application.profileFields: must be an array of field-name strings\");\n }\n if (a?.crmFields !== undefined && (!Array.isArray(a.crmFields) || !a.crmFields.every((f) => typeof f === \"string\" && f !== \"\"))) {\n throw new Error(\"defineChapter.application.crmFields: must be an array of field-name strings\");\n }\n // Conditions are checked when the chapter is defined, so a typo fails at\n // startup rather than quietly misbehaving on a live join page. Fields that\n // fail open at runtime are the deliberate second line of defence, not this.\n const conditions = a?.conditions ?? {};\n for (const [field, declared] of Object.entries(conditions)) {\n for (const key of [\"visibleWhen\", \"requiredWhen\"] as const) {\n const expression = declared?.[key];\n if (expression === undefined) continue;\n if (typeof expression !== \"string\" || !expression.trim()) {\n throw new Error(`defineChapter.application.conditions.${field}.${key}: must be a non-empty CEL condition`);\n }\n assertFieldCondition(expression, `defineChapter.application.conditions.${field}.${key}`);\n }\n }\n return {\n required,\n optional,\n conditions,\n maxLen: a?.maxLen ?? {},\n defaultMaxLen: a?.defaultMaxLen ?? 2000,\n bodyCap: a?.bodyCap ?? 32768,\n requireDisclaimerAck: a?.requireDisclaimerAck ?? true,\n profileFields: a?.profileFields ?? [],\n crmFields: a?.crmFields ?? [],\n maxArrayLen: a?.maxArrayLen ?? 100,\n validateEmail: a?.validateEmail ?? true,\n };\n}\n\n// A permissive email shape check: one @, a dot-bearing domain, no whitespace.\n// Deliberately not RFC-exhaustive — the goal is to reject \"notanemail\" before it\n// fails the downstream Clerk create, not to adjudicate exotic-but-valid addresses.\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\n\n/** Whether a string looks like an email address (see {@link EMAIL_RE}). Exported\n * so a site building its own submit path applies the same rule chapter does. */\nexport function isValidEmail(value: unknown): boolean {\n return typeof value === \"string\" && EMAIL_RE.test(value);\n}\n\n/** Bound an array-valued field: drop non-primitive elements and cap the length,\n * so a client cannot post an unbounded array. Non-arrays pass through unchanged. */\nexport function clampArray(value: unknown, max: number): unknown {\n if (!Array.isArray(value)) return value;\n return value.filter((x) => typeof x === \"string\" || typeof x === \"number\" || typeof x === \"boolean\").slice(0, max);\n}\n\n/** Whether a submit body carries a genuine disclaimer acknowledgement. Accepts\n * the boolean an API client sends and the string a plain HTML form posts. */\nexport function hasDisclaimerAck(fields: Record<string, unknown>): boolean {\n return fields.disclaimerAck === true || fields.disclaimerAck === \"true\";\n}\n\n// Clerk carries these as first-class user fields, so repeating them in\n// public_metadata would be duplicated state that can drift.\nconst IDENTITY_FIELDS = new Set([\"email\", \"firstName\", \"lastName\"]);\n\n/**\n * The applicant profile written to the Clerk account's backend-only\n * `private_metadata.profile`. Projects each configured non-identity field, plus\n * `focus` (clamped), but ONLY those in `application.profileFields`. Derived\n * from config, so a site's own field names project without this package knowing\n * them. Pure; returns `undefined` when there is nothing to write.\n */\nexport function applicantProfile(\n chapter: Chapter,\n fields: Record<string, unknown>,\n): Record<string, unknown> | undefined {\n const app = chapter.application;\n const allowed = (f: string): boolean => app.profileFields.includes(f);\n const profile: Record<string, unknown> = {};\n for (const f of [...app.required, ...app.optional]) {\n if (IDENTITY_FIELDS.has(f) || !allowed(f)) continue;\n const v = fields[f];\n if (typeof v === \"string\" && v.trim() !== \"\") profile[f] = v.trim();\n }\n if (fields.focus !== undefined && allowed(\"focus\")) profile.focus = clampArray(fields.focus, app.maxArrayLen);\n return Object.keys(profile).length > 0 ? profile : undefined;\n}\n\n/** A validated submission, or a 400-worthy validation error the route returns.\n * `disclaimerAckAt` reports what THIS request recorded — a number when consent\n * was stamped, `null` when none was supplied. It is always present so a missing\n * consent record is visible in the response rather than silently absent from a\n * row nobody reads until an audit. */\nexport type SubmitResult =\n | { ok: true; id: string; duplicate: boolean; status: string; disclaimerAckAt: number | null }\n | { ok: false; error: string };\n\n/**\n * Submit a membership application (B2 + B3). Validates the configured required\n * fields + max lengths, writes the `applications` row at the pipeline's initial\n * status, and — when the client supplies a `submissionId` — stamps it as the\n * transaction's mutationId (`join:${submissionId}`) so a double-tap can never\n * create two applications. The application id is derived from that same stable\n * input, so the duplicate response returns the first request's canonical id\n * rather than a fresh, nonexistent one. Idempotency is package-enforced.\n * `now`/`newId` are injected (deterministic in tests).\n */\nexport async function submitApplication(\n db: ChapterDb,\n chapter: Chapter,\n fields: Record<string, unknown>,\n opts: {\n submissionId?: string;\n groupId?: string;\n now: number;\n newId: () => string;\n /** Tier ids this chapter offers. A posted `tierId` outside it is refused;\n * omit to accept any (pre-tier callers). */\n tierIds?: readonly string[];\n /** Effective one-use waiver selected by the server, never by the client. */\n admissionGrant?: AdmissionGrantRow;\n /** Server-validated gift offer selected from active signed control. */\n giftOfferId?: string;\n },\n): Promise<SubmitResult> {\n const app = chapter.application;\n // Requiredness is resolved against the answers, not read off a static list,\n // so a conditionally-hidden field is not demanded and a conditionally-\n // required one cannot be skipped by posting straight to this route. The\n // renderer calls the same resolver, so the form and the validator cannot\n // disagree. With no conditions declared this is exactly the old static loop.\n const fieldStates = resolveFieldStates(app.conditions ?? {}, fields, app.required);\n for (const [f, state] of Object.entries(fieldStates)) {\n if (!state.required) continue;\n const v = fields[f];\n if (typeof v !== \"string\" || v.trim() === \"\") return { ok: false, error: `${f} is required` };\n }\n for (const f of [...app.required, ...app.optional]) {\n const v = fields[f];\n const cap = app.maxLen[f] ?? app.defaultMaxLen;\n if (typeof v === \"string\" && v.length > cap) return { ok: false, error: `${f} exceeds ${cap} characters` };\n }\n // A malformed email can only fail the downstream Clerk create; reject it here\n // as a clean 400. A valid application always has a valid email, so no genuine\n // submission is newly rejected.\n if (app.validateEmail && typeof fields.email === \"string\" && !isValidEmail(fields.email.trim())) {\n return { ok: false, error: \"email must be a valid email address\" };\n }\n\n const acked = hasDisclaimerAck(fields);\n if (app.requireDisclaimerAck && !acked) {\n return { ok: false, error: \"disclaimerAck is required\" };\n }\n\n const id = opts.submissionId\n ? await applicationIdForSubmission(opts.submissionId)\n : opts.newId();\n const row: Record<string, unknown> = { id, status: chapter.pipeline.initial, createdAt: opts.now };\n for (const f of [...app.required, ...app.optional]) {\n // A field the conditions hid was never asked, so a value for it is stale\n // or forged. Storing it would answer a question on the applicant's behalf.\n if (fieldStates[f]?.visible === false) continue;\n if (typeof fields[f] === \"string\") row[f] = (fields[f] as string).trim();\n }\n if (fields.focus !== undefined) row.focus = clampArray(fields.focus, app.maxArrayLen);\n if (opts.groupId) row.groupId = opts.groupId;\n if (typeof fields.email === \"string\" && isValidEmail(fields.email.trim())) {\n row.emailNormalized = normalizeChapterEmail(fields.email);\n }\n if (opts.admissionGrant?.decision === \"waive_interview\") {\n row.admissionGrantId = opts.admissionGrant.id;\n row.admissionSource = opts.admissionGrant.sourceScope;\n row.interviewWaivedAt = opts.now;\n }\n if (opts.giftOfferId) row.giftOfferId = opts.giftOfferId;\n // A tier decides what this member is charged, so the posted id is checked\n // against what the chapter actually offers rather than trusted. An unknown\n // id is refused instead of silently dropped: dropping it would bill the\n // applicant whatever the fallback tier costs.\n if (typeof fields.tierId === \"string\" && fields.tierId) {\n if (opts.tierIds && !opts.tierIds.includes(fields.tierId)) {\n return { ok: false, error: \"tierId is not an offered tier\" };\n }\n row.tierId = fields.tierId;\n }\n // The disclaimer acknowledgement is a compliance record, so it is stamped from\n // the server clock on a genuine ack and left absent otherwise — a client-supplied\n // timestamp would be forgeable, and a row that always carries one would record\n // consent nobody gave.\n if (acked) row.disclaimerAckAt = opts.now;\n\n const ops: Parameters<ChapterDb[\"transact\"]>[0] = [\n { t: \"update\", ns: \"applications\", id, attrs: row },\n ];\n if (opts.admissionGrant?.decision === \"waive_interview\") {\n ops.push({ t: \"update\", ns: \"admissionGrants\", id: opts.admissionGrant.id, attrs: {\n consumedAt: opts.now,\n consumedApplicationId: id,\n } });\n }\n const { duplicate } = await db.transact(\n ops,\n opts.submissionId ? { mutationId: `join:${opts.submissionId}` } : undefined,\n );\n return { ok: true, id, duplicate, status: chapter.pipeline.initial, disclaimerAckAt: acked ? opts.now : null };\n}\n\n/** The `groups`-row fields the join config exposes. */\nexport interface JoinConfigGroup {\n id: string;\n name: string;\n standardPriceCents?: number;\n foundingDiscountCents?: number;\n disclaimerText?: string;\n refundPolicyText?: string;\n trustCopy?: string;\n commitmentText?: string;\n normsText?: string;\n}\n\n/**\n * The public join config (B1) a site's join page reads: copy + prices from the\n * group row plus `paymentsReady`. When payments aren't wired the join flow drops\n * the payment step (C2) — the worker computes `paymentsReady` from the group's\n * Stripe keys + vault secret. Pure.\n *\n * `tiers` carries the offerable membership tiers. It is additive: the legacy\n * `standardPriceCents`/`foundingDiscountCents` fields still describe the first\n * tier, so a join page written before tiers keeps rendering unchanged. A free\n * tier appears here with `free: true` even when Stripe is unconfigured, because\n * nothing needs charging for it.\n */\nexport function joinConfig(\n group: JoinConfigGroup,\n paymentsReady: boolean,\n tiers: readonly JoinConfigTier[] = [],\n conditions: Readonly<Record<string, FieldConditions>> = {},\n): Record<string, unknown> {\n return {\n id: group.id,\n name: group.name,\n standardPriceCents: group.standardPriceCents ?? 0,\n foundingDiscountCents: group.foundingDiscountCents ?? 0,\n tiers: [...tiers],\n // The browser evaluates the same conditions the server enforces.\n conditions,\n disclaimerText: group.disclaimerText ?? \"\",\n refundPolicyText: group.refundPolicyText ?? \"\",\n trustCopy: group.trustCopy ?? \"\",\n commitmentText: group.commitmentText ?? \"\",\n normsText: group.normsText ?? \"\",\n paymentsReady,\n };\n}\n","// Application creates use a caller-stable submission id as their database\n// mutation id. The entity id must be derived from that same stable input: if a\n// committed request is retried, the database correctly skips the new ops and\n// Chapter must still return the id of the row written by the first request.\n\nconst APPLICATION_ID_DOMAIN = \"odla-ai/chapter/application/v1:\";\n\n/**\n * Derive the UUID-shaped capability for an idempotent application submission.\n * SHA-256 prevents a caller from choosing a submission id that overwrites a\n * known application id; UUIDv8 bits preserve the identifier shape consumers\n * already expect.\n */\nexport async function applicationIdForSubmission(submissionId: string): Promise<string> {\n const input = new TextEncoder().encode(`${APPLICATION_ID_DOMAIN}${submissionId}`);\n const bytes = new Uint8Array(await crypto.subtle.digest(\"SHA-256\", input)).slice(0, 16);\n bytes[6] = (bytes[6]! & 0x0f) | 0x80;\n bytes[8] = (bytes[8]! & 0x3f) | 0x80;\n const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","/**\n * Normalize an email address for Chapter identity lookups.\n *\n * Chapter treats the address literally: surrounding whitespace and ASCII case\n * are insignificant, but the local part is otherwise preserved. In\n * particular, provider-specific aliases are never collapsed, so\n * `foo+bar@gmail.com` and `foo@gmail.com` remain distinct applicants,\n * admission decisions, purchasers, and beneficiaries.\n */\nexport function normalizeChapterEmail(email: string): string {\n return email.trim().toLowerCase();\n}\n","import type { Attr, AttrType, Entity, ResolvedApplication } from \"./types\";\n\nconst attr = (type: AttrType, flags: { unique?: boolean; indexed?: boolean; optional?: boolean } = {}): Attr => ({\n type, unique: flags.unique ?? false, indexed: flags.indexed ?? false, optional: flags.optional ?? false,\n});\n\nconst APPLICATION_INPUT_FIELDS = new Set([\n \"firstName\", \"lastName\", \"email\", \"referral\", \"referralName\", \"whoYouAre\",\n \"focus\", \"linkedin\", \"message\", \"phone\", \"state\",\n]);\n\nconst applicationAttrs: Record<string, Attr> = {\n id: attr(\"string\", { unique: true, indexed: true }), firstName: attr(\"string\"), lastName: attr(\"string\"),\n email: attr(\"string\", { indexed: true }), referral: attr(\"string\"), referralName: attr(\"string\", { optional: true }),\n whoYouAre: attr(\"string\"), focus: attr(\"json\"), linkedin: attr(\"string\", { optional: true }), message: attr(\"string\"),\n status: attr(\"string\", { indexed: true }), createdAt: attr(\"number\", { indexed: true }),\n meetingAt: attr(\"number\", { indexed: true, optional: true }), meetingLink: attr(\"string\", { optional: true }),\n clerkUserId: attr(\"string\", { indexed: true, optional: true }), clerkPrivateMetadataSyncedAt: attr(\"number\", { optional: true }),\n phone: attr(\"string\", { optional: true }), state: attr(\"string\", { optional: true }),\n groupId: attr(\"string\", { indexed: true, optional: true }), tierId: attr(\"string\", { indexed: true, optional: true }),\n stripeCustomerId: attr(\"string\", { indexed: true, optional: true }),\n stripeSubscriptionId: attr(\"string\", { indexed: true, optional: true }), renewalAt: attr(\"number\", { optional: true }),\n disclaimerAckAt: attr(\"number\", { optional: true }), refundPolicyAckAt: attr(\"number\", { optional: true }),\n prepEmailSentAt: attr(\"number\", { optional: true }), canceled: attr(\"boolean\", { optional: true }),\n emailNormalized: attr(\"string\", { indexed: true, optional: true }),\n admissionGrantId: attr(\"string\", { unique: true, indexed: true, optional: true }),\n admissionSource: attr(\"string\", { indexed: true, optional: true }), interviewWaivedAt: attr(\"number\", { optional: true }),\n giftOfferId: attr(\"string\", { optional: true, indexed: true }),\n giftIntentId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n giftClaimId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n giftOrderId: attr(\"string\", { optional: true, indexed: true }), giftPaidAt: attr(\"number\", { optional: true, indexed: true }),\n giftRevokedAt: attr(\"number\", { optional: true, indexed: true }),\n giftCheckoutStartedAt: attr(\"number\", { optional: true, indexed: true }),\n};\n\n/** Resolve the site-configurable application inputs without exposing operational fields. */\nexport function applicationsFor(application: ResolvedApplication): Entity {\n const attrs: Record<string, Attr> = {};\n for (const [name, spec] of Object.entries(applicationAttrs)) {\n attrs[name] = { ...spec, optional: APPLICATION_INPUT_FIELDS.has(name) ? true : spec.optional };\n }\n const apply = (field: string, optional: boolean): void => {\n const existing = Object.hasOwn(attrs, field) ? attrs[field] : undefined;\n if (existing && !APPLICATION_INPUT_FIELDS.has(field)) throw new Error(`defineChapter.application: field \"${field}\" is reserved by the applications schema`);\n if (existing && existing.type !== \"string\") throw new Error(`defineChapter.application: field \"${field}\" is not a configurable string field`);\n Object.defineProperty(attrs, field, {\n value: existing ? { ...existing, optional } : attr(\"string\", { optional }),\n enumerable: true, configurable: true, writable: true,\n });\n };\n for (const field of application.required) apply(field, false);\n for (const field of application.optional) apply(field, true);\n return { attrs };\n}\n","import type { Attr, AttrType, Entity } from \"./types\";\n\nconst attr = (type: AttrType, flags: { unique?: boolean; indexed?: boolean; optional?: boolean } = {}): Attr => ({\n type,\n unique: flags.unique ?? false,\n indexed: flags.indexed ?? false,\n optional: flags.optional ?? false,\n});\nconst id = (): Attr => attr(\"string\", { unique: true, indexed: true });\n\n/** Operational Parent and Chapter admission decisions, never publicly readable. */\nexport const admissionGrantsEntity: Entity = {\n attrs: {\n id: id(),\n sourceGrantId: attr(\"string\", { indexed: true }),\n sourceScope: attr(\"string\", { indexed: true }),\n sourceId: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n email: attr(\"string\"),\n emailNormalized: attr(\"string\", { indexed: true }),\n decision: attr(\"string\", { indexed: true }),\n note: attr(\"string\", { optional: true }),\n active: attr(\"boolean\", { indexed: true }),\n sourceRevision: attr(\"number\", { optional: true, indexed: true }),\n createdAt: attr(\"number\", { indexed: true }),\n createdBy: attr(\"string\", { optional: true, indexed: true }),\n updatedAt: attr(\"number\", { optional: true, indexed: true }),\n updatedBy: attr(\"string\", { optional: true, indexed: true }),\n expiresAt: attr(\"number\", { optional: true, indexed: true }),\n revokedAt: attr(\"number\", { optional: true, indexed: true }),\n revokedBy: attr(\"string\", { optional: true, indexed: true }),\n consumedAt: attr(\"number\", { optional: true, indexed: true }),\n consumedApplicationId: attr(\"string\", { optional: true, indexed: true }),\n },\n};\n\n/** Immutable acknowledgements for signed Parent admission documents. */\nexport const admissionGrantRevisionsEntity: Entity = {\n attrs: {\n id: id(),\n sourceId: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }),\n revision: attr(\"number\", { indexed: true }),\n digest: attr(\"string\", { indexed: true }),\n active: attr(\"boolean\", { indexed: true }),\n receivedAt: attr(\"number\", { indexed: true }),\n },\n};\n","import type { Attr, AttrType, Entity } from \"./types\";\n\nconst attr = (type: AttrType, flags: { unique?: boolean; indexed?: boolean; optional?: boolean } = {}): Attr => ({\n type, unique: flags.unique ?? false, indexed: flags.indexed ?? false, optional: flags.optional ?? false,\n});\nconst id = (): Attr => attr(\"string\", { unique: true, indexed: true });\n\n/** Pre-payment gift checkout state. It holds only a code hash, never plaintext. */\nexport const giftPurchaseIntentsEntity: Entity = { attrs: {\n id: id(), chapterId: attr(\"string\", { indexed: true }), environment: attr(\"string\", { indexed: true }),\n purchaserType: attr(\"string\", { indexed: true }), purchaserApplicationId: attr(\"string\", { optional: true, indexed: true }),\n purchaserUserId: attr(\"string\", { optional: true, indexed: true }), purchaserEmailNormalized: attr(\"string\", { indexed: true }),\n offerId: attr(\"string\", { indexed: true }), offerSnapshot: attr(\"json\"), status: attr(\"string\", { indexed: true }),\n codeHash: attr(\"string\", { indexed: true }), codeVersion: attr(\"number\"), codeIssuedAt: attr(\"number\"),\n providerObjectId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n providerCustomerId: attr(\"string\", { optional: true, indexed: true }), checkoutStartedAt: attr(\"number\", { optional: true }),\n paidAt: attr(\"number\", { optional: true, indexed: true }), claimId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n createdAt: attr(\"number\", { indexed: true }), updatedAt: attr(\"number\", { indexed: true }),\n} };\n\n/** Immutable provider-authorized gift purchase evidence. */\nexport const giftOrdersEntity: Entity = { attrs: {\n id: id(), intentId: attr(\"string\", { unique: true, indexed: true }), chapterId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }), offerId: attr(\"string\", { indexed: true }), offerSnapshot: attr(\"json\"),\n purchaserType: attr(\"string\", { indexed: true }), purchaserApplicationId: attr(\"string\", { optional: true, indexed: true }),\n purchaserUserId: attr(\"string\", { optional: true, indexed: true }), purchaserEmailNormalized: attr(\"string\", { indexed: true }),\n providerEventId: attr(\"string\", { unique: true, indexed: true }), providerObjectId: attr(\"string\", { indexed: true }),\n amountCents: attr(\"number\"), currency: attr(\"string\"), billingMode: attr(\"string\"), createdAt: attr(\"number\", { indexed: true }),\n} };\n\n/** Single-use beneficiary bearer claim. Buyer list routes never return its hash. */\nexport const giftClaimsEntity: Entity = { attrs: {\n id: id(), orderId: attr(\"string\", { unique: true, indexed: true }), intentId: attr(\"string\", { unique: true, indexed: true }),\n chapterId: attr(\"string\", { indexed: true }), offerId: attr(\"string\", { indexed: true }), target: attr(\"json\"),\n purchaserApplicationId: attr(\"string\", { optional: true, indexed: true }), purchaserUserId: attr(\"string\", { optional: true, indexed: true }),\n purchaserEmailNormalized: attr(\"string\", { indexed: true }), codeHash: attr(\"string\", { unique: true, indexed: true }),\n codeVersion: attr(\"number\"), rotationCount: attr(\"number\"), codeIssuedAt: attr(\"number\"), codeExpiresAt: attr(\"number\", { indexed: true }),\n attemptCount: attr(\"number\"), attemptWindowStartedAt: attr(\"number\"), status: attr(\"string\", { indexed: true }),\n redeemedAt: attr(\"number\", { optional: true, indexed: true }), beneficiaryEmailNormalized: attr(\"string\", { optional: true, indexed: true }),\n beneficiaryUserId: attr(\"string\", { optional: true, indexed: true }), applicationId: attr(\"string\", { optional: true, unique: true, indexed: true }),\n entitlementId: attr(\"string\", { optional: true, unique: true, indexed: true }), rotatedAt: attr(\"number\", { optional: true }),\n revokedAt: attr(\"number\", { optional: true, indexed: true }), revokedReason: attr(\"string\", { optional: true }), createdAt: attr(\"number\", { indexed: true }),\n} };\n\n/** Non-membership beneficiary entitlements created by redeemed gift claims. */\nexport const giftEntitlementsEntity: Entity = { attrs: {\n id: id(), claimId: attr(\"string\", { unique: true, indexed: true }), orderId: attr(\"string\", { indexed: true }),\n chapterId: attr(\"string\", { indexed: true }), entitlementKey: attr(\"string\", { indexed: true }),\n beneficiaryEmailNormalized: attr(\"string\", { indexed: true }), beneficiaryUserId: attr(\"string\", { optional: true, indexed: true }),\n active: attr(\"boolean\", { indexed: true }), createdAt: attr(\"number\", { indexed: true }), revokedAt: attr(\"number\", { optional: true }),\n} };\n\n/** Coarse requester buckets that bound public redemption attempts. */\nexport const giftRedemptionAttemptsEntity: Entity = { attrs: {\n id: id(), chapterId: attr(\"string\", { indexed: true }), bucket: attr(\"string\", { indexed: true }),\n attemptCount: attr(\"number\"), windowStartedAt: attr(\"number\", { indexed: true }), updatedAt: attr(\"number\"),\n} };\n","// The chapter's own odla-db namespaces: the operational membership tables\n// (applications, groups, meetings, emailLog) plus the auth tables the resolved\n// auth policy selects — the `admins` allowlist (source \"table\") and/or the\n// read-only `superAdmins` tier. All deny-all. The `crm_*` namespaces are\n// contributed separately by @odla-ai/crm's integration and merged by the CLI.\nimport type {\n Attr,\n AttrType,\n DbRules,\n DbSchema,\n Entity,\n ChapterMode,\n ResolvedApplication,\n ResolvedAuth,\n} from \"./types\";\nimport { resolveApplication } from \"./member\";\nimport { applicationsFor } from \"./schema-applications\";\nimport { admissionGrantRevisionsEntity, admissionGrantsEntity } from \"./schema-admission\";\nimport {\n giftClaimsEntity, giftEntitlementsEntity, giftOrdersEntity,\n giftPurchaseIntentsEntity, giftRedemptionAttemptsEntity,\n} from \"./schema-gifts\";\n\nfunction attr(type: AttrType, flags: { unique?: boolean; indexed?: boolean; optional?: boolean } = {}): Attr {\n return {\n type,\n unique: flags.unique ?? false,\n indexed: flags.indexed ?? false,\n optional: flags.optional ?? false,\n };\n}\nconst id = (): Attr => attr(\"string\", { unique: true, indexed: true });\n\n// The allowlist that gates admin access in BOTH modes. Studio-write-only:\n// deny-all, and no worker route ever writes it. Creation time is odla-db's\n// built-in $createdAt. One row per admin, keyed by lowercased email.\nconst admins: Entity = {\n attrs: {\n id: id(),\n email: attr(\"string\", { unique: true, indexed: true }),\n name: attr(\"string\", { optional: true }),\n note: attr(\"string\", { optional: true }),\n },\n};\n\n// The super-admin tier: the ONLY tier that may create or modify admins. A\n// separate, app-READ-ONLY entity — deny-all like every namespace AND no worker\n// route ever writes it, so membership can only be set in the odla Studio data\n// browser, never from the app or an injected page script. One row per\n// super-admin, keyed by lowercased email.\nconst superAdmins: Entity = {\n attrs: {\n id: id(),\n email: attr(\"string\", { unique: true, indexed: true }),\n note: attr(\"string\", { optional: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Leader-private annotations on records that remain authoritative in a\n// follower CRM. `recordKey` is the stable target/type/id tuple used for bounded\n// reads; notes never cross the federation edge or mutate the follower.\nconst networkNotes: Entity = {\n attrs: {\n id: id(),\n recordKey: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n recordType: attr(\"string\", { indexed: true }),\n recordId: attr(\"string\", { indexed: true }),\n body: attr(\"string\"),\n authorId: attr(\"string\", { indexed: true }),\n authorEmail: attr(\"string\", { optional: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Immutable signup-control revisions. Exactly one row is active; older rows are\n// retained for audit/rollback while applicant traffic reads local state only.\nconst signupControls: Entity = {\n attrs: {\n id: id(),\n sourceId: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }),\n revision: attr(\"number\", { indexed: true }),\n digest: attr(\"string\", { indexed: true }),\n document: attr(\"json\"),\n active: attr(\"boolean\", { indexed: true }),\n receivedAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Immutable Parent member-content revisions. Exactly one row is active per\n// environment; Chapter-owned content lives in a separate singleton below so a\n// replay or replacement from the Parent cannot overwrite local authority.\nconst memberContentControls: Entity = {\n attrs: {\n id: id(),\n sourceId: attr(\"string\", { indexed: true }),\n targetId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }),\n revision: attr(\"number\", { indexed: true }),\n digest: attr(\"string\", { indexed: true }),\n document: attr(\"json\"),\n active: attr(\"boolean\", { indexed: true }),\n receivedAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// One complete Chapter-owned authoring layer per environment. Admin writes are\n// revision-guarded and never share a row with inherited Parent content.\nconst memberContentLocal: Entity = {\n attrs: {\n id: id(),\n chapterId: attr(\"string\", { indexed: true }),\n environment: attr(\"string\", { indexed: true }),\n revision: attr(\"number\", { indexed: true }),\n document: attr(\"json\"),\n updatedAt: attr(\"number\", { indexed: true }),\n updatedBy: attr(\"string\", { optional: true }),\n },\n};\n\n// Per-group settings — prices, policy copy, email templates, scheduling — never\n// in code. Seeded once from the defineChapter config (see group.ts).\nconst groups: Entity = {\n attrs: {\n id: id(),\n name: attr(\"string\"),\n standardPriceCents: attr(\"number\"),\n foundingDiscountCents: attr(\"number\"),\n stripePriceId: attr(\"string\", { optional: true }),\n stripePublishableKey: attr(\"string\", { optional: true }),\n notificationEmail: attr(\"string\"),\n replyTo: attr(\"string\"),\n debugEmail: attr(\"string\", { optional: true }),\n calendarLink: attr(\"string\", { optional: true }),\n disclaimerText: attr(\"string\"),\n refundPolicyText: attr(\"string\"),\n trustCopy: attr(\"string\"),\n commitmentText: attr(\"string\", { optional: true }),\n normsText: attr(\"string\", { optional: true }),\n emailTemplates: attr(\"json\"),\n schedulingJson: attr(\"json\", { optional: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// One row per membership tier a group offers. The price lives here rather than\n// on the group so a chapter can offer several, and so a free tier (priceCents\n// 0, no stripePriceId) is expressible at all. Deny-all like every namespace:\n// tiers are set in Studio or seeded from the chapter config, never written by a\n// join-flow route.\nconst tiers: Entity = {\n attrs: {\n id: id(),\n groupId: attr(\"string\", { indexed: true }),\n name: attr(\"string\"),\n priceCents: attr(\"number\"),\n stripePriceId: attr(\"string\", { optional: true }),\n blurb: attr(\"string\", { optional: true }),\n sortOrder: attr(\"number\", { indexed: true }),\n active: attr(\"boolean\", { indexed: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Intro-call meetings: the source of truth for scheduling; Google Calendar is a\n// projection. Drift fields record when Google disagrees with us.\nconst meetings: Entity = {\n attrs: {\n id: id(),\n applicationId: attr(\"string\", { indexed: true }),\n groupId: attr(\"string\", { indexed: true }),\n startAt: attr(\"number\", { indexed: true }),\n endAt: attr(\"number\"),\n timezone: attr(\"string\"),\n status: attr(\"string\", { indexed: true }),\n googleEventId: attr(\"string\", { indexed: true, optional: true }),\n meetUrl: attr(\"string\", { optional: true }),\n htmlLink: attr(\"string\", { optional: true }),\n drift: attr(\"string\", { indexed: true, optional: true }),\n driftGoogleStartAt: attr(\"number\", { optional: true }),\n driftDetectedAt: attr(\"number\", { optional: true }),\n adoptedFromGoogleAt: attr(\"number\", { optional: true }),\n createdAt: attr(\"number\", { indexed: true }),\n },\n};\n\n// Audit of every transactional send.\nconst emailLog: Entity = {\n attrs: {\n id: id(),\n groupId: attr(\"string\", { indexed: true }),\n applicationId: attr(\"string\", { indexed: true, optional: true }),\n to: attr(\"string\", { indexed: true }),\n template: attr(\"string\", { indexed: true }),\n subject: attr(\"string\"),\n body: attr(\"string\", { optional: true }),\n transport: attr(\"string\"),\n messageId: attr(\"string\", { optional: true }),\n redirected: attr(\"boolean\", { optional: true }),\n dedupeKey: attr(\"string\", { indexed: true, optional: true }),\n error: attr(\"string\", { optional: true }),\n sentAt: attr(\"number\", { indexed: true }),\n },\n};\n\n/** The chapter's own schema + deny-all rules for a mode + auth policy.\n *\n * In chapter mode, the optional {@link ResolvedApplication} supplies the exact\n * required/optional application string attrs. Omit it for the reference form.\n * Built-in attrs retain their types/indexes; site-defined fields become string\n * attrs, while package-owned operational attrs cannot be repurposed as inputs.\n *\n * Operational tables (`applications`/`groups`/`meetings`/`emailLog`) are added in\n * `chapter` mode only. The auth tables follow {@link ResolvedAuth}: `source:\n * \"table\"` adds the `admins` allowlist (hub/BNF); `superAdmins` adds the\n * read-only super-admin tier (default on for the `\"claim\"` ladder). A `\"claim\"`\n * chapter therefore emits the reference namespace set — `applications`,\n * `groups`, `meetings`, `emailLog`, `superAdmins` — with no `admins` table. */\nexport function chapterDb(\n mode: ChapterMode,\n auth: ResolvedAuth,\n includeNetworkNotes = false,\n application: ResolvedApplication = resolveApplication(undefined),\n includeSignupControl = false,\n includeMemberContent = false,\n): { schema: DbSchema; rules: DbRules } {\n const entities: Record<string, Entity> = {};\n if (mode === \"chapter\") {\n entities.applications = applicationsFor(application);\n entities.groups = groups;\n entities.tiers = tiers;\n entities.meetings = meetings;\n entities.emailLog = emailLog;\n entities.admissionGrants = admissionGrantsEntity;\n entities.admissionGrantRevisions = admissionGrantRevisionsEntity;\n entities.giftPurchaseIntents = giftPurchaseIntentsEntity;\n entities.giftOrders = giftOrdersEntity;\n entities.giftClaims = giftClaimsEntity;\n entities.giftEntitlements = giftEntitlementsEntity;\n entities.giftRedemptionAttempts = giftRedemptionAttemptsEntity;\n if (includeSignupControl) entities.signupControls = signupControls;\n if (includeMemberContent) {\n entities.memberContentControls = memberContentControls;\n entities.memberContentLocal = memberContentLocal;\n }\n }\n if (auth.source === \"table\") entities.admins = admins;\n if (auth.superAdmins) entities.superAdmins = superAdmins;\n if (includeNetworkNotes) entities.networkNotes = networkNotes;\n const schema: DbSchema = { entities, links: {} };\n const rules: DbRules = {};\n for (const ns of Object.keys(entities)) {\n rules[ns] = { view: \"false\", create: \"false\", update: \"false\", delete: \"false\" };\n }\n return { schema, rules };\n}\n","// Per-mode default CRM configs. Consumers pass their own via defineChapter's\n// `crm`; these are sensible starting points. Both modes share the canonical\n// people + businesses graph, while `chapter` additionally feeds the person\n// pipeline from applications through the operational package routes.\nimport type { CrmConfig } from \"@odla-ai/crm\";\nimport type { ChapterMode } from \"./types\";\n\nconst TEMPLATES: CrmConfig[\"templates\"] = {\n personal: {\n class: \"transactional\",\n vars: [\"firstName\", \"subject\", \"body\"],\n defaults: { subject: \"{{subject}}\", text: \"{{body}}\" },\n },\n announcement: {\n class: \"marketing\",\n vars: [\"firstName\", \"subject\", \"body\", \"unsubscribeUrl\"],\n defaults: { subject: \"{{subject}}\", text: \"{{body}}\\n\\n{{unsubscribeUrl}}\" },\n },\n};\n\nfunction personType(): NonNullable<CrmConfig[\"types\"]>[string] {\n return {\n label: \"Person\",\n labelPlural: \"People\",\n nameField: \"name\",\n emailField: \"email\",\n fields: {\n name: { type: \"string\", label: \"Name\", required: true },\n email: { type: \"email\", label: \"Email\" },\n firstName: { type: \"string\", label: \"First name\" },\n lastName: { type: \"string\", label: \"Last name\" },\n phone: { type: \"string\", label: \"Phone\" },\n state: { type: \"string\", label: \"State\", slot: \"s1\" },\n whoYouAre: { type: \"string\", label: \"Who they are\", slot: \"s2\" },\n referral: { type: \"string\", label: \"Referral source\", slot: \"s3\" },\n linkedin: { type: \"string\", label: \"LinkedIn\" },\n focus: { type: \"json\", label: \"Focus areas\" },\n message: { type: \"string\", label: \"Intro message\" },\n },\n pipeline: {\n stages: [\n { id: \"submitted\", label: \"Submitted\" },\n { id: \"paid_pending_vetting\", label: \"Paid, pending vetting\" },\n { id: \"call_scheduled\", label: \"Call scheduled\" },\n { id: \"interviewed\", label: \"Interviewed\" },\n { id: \"approved\", label: \"Approved\" },\n { id: \"declined\", label: \"Declined\" },\n { id: \"refunded\", label: \"Refunded\" },\n ],\n },\n facets: { identity: true, email: true, rank: \"manual\" },\n };\n}\n\nfunction companyType(): NonNullable<CrmConfig[\"types\"]>[string] {\n return {\n label: \"Business\",\n labelPlural: \"Businesses\",\n nameField: \"name\",\n fields: {\n name: { type: \"string\", label: \"Name\", required: true },\n domain: { type: \"string\", label: \"Domain / website\", slot: \"s1\" },\n industry: { type: \"string\", label: \"Industry\", slot: \"s2\" },\n location: { type: \"string\", label: \"Location\", slot: \"s3\" },\n chapter: { type: \"string\", label: \"Chapter\", slot: \"s4\" },\n linkedin: { type: \"string\", label: \"LinkedIn\" },\n notes: { type: \"string\", label: \"Notes\" },\n },\n facets: { rank: \"manual\" },\n };\n}\n\n/** The default shared CRM graph: people (with the application/member pipeline)\n * plus businesses and the `works_at` relation, in both modes. */\nexport function defaultCrm(_mode: ChapterMode): CrmConfig {\n return {\n types: { person: personType(), company: companyType() },\n relations: { works_at: { from: \"person\", to: \"company\", label: \"works at\", reverseLabel: \"team\" } },\n templates: TEMPLATES,\n };\n}\n","// Build the seed `groups` row from a defineChapter config. This is the whole\n// per-chapter payload the worker reads at runtime (prices/policy/emails/\n// scheduling), so nothing brand-specific is hardcoded in the worker. createdAt\n// is stamped by the integration/seed layer, not here.\nimport type { ChapterConfig, ChapterScheduling } from \"./types\";\n\nconst DEFAULT_SCHEDULING: Required<Omit<ChapterScheduling, \"summaryTemplate\">> = {\n slotMinutes: 45,\n days: [1, 2, 3, 4, 5],\n startHour: 9,\n endHour: 17,\n timezone: \"America/Los_Angeles\",\n minNoticeHours: 24,\n windowDays: 14,\n};\n\nfunction defaultEmailTemplates(name: string): Record<string, { subject: string; text: string }> {\n const sign = `\\n\\nWarmly,\\n${name}`;\n return {\n adminNotification: {\n subject: `New application: {{firstName}} {{lastName}}`,\n text: `A new application came in for ${name}.\\n\\nName: {{firstName}} {{lastName}}\\nEmail: {{email}}`,\n },\n paymentConfirmation: {\n subject: `Welcome to ${name}`,\n text: `Hi {{firstName}},\\n\\nYour membership payment is confirmed. We'll be in touch to schedule your intro call.${sign}`,\n },\n prepEmail: {\n subject: `Your ${name} intro call`,\n text: `Hi {{firstName}},\\n\\nLooking forward to our call at {{meetingTime}}. {{meetingLink}}${sign}`,\n },\n onboardingInvite: {\n subject: `You're in, ${name}`,\n text: `Hi {{firstName}},\\n\\nWelcome to ${name}. Your member area is here: {{membersUrl}}${sign}`,\n },\n };\n}\n\n/** The `groups` row (attrs) for `chapter` mode. Missing config falls back to\n * empty copy / defaults, so a minimal config still provisions cleanly. */\nexport function buildGroupSeed(config: ChapterConfig): Record<string, unknown> {\n const prices = config.prices;\n const emails = config.emails;\n const policy = config.policy ?? {};\n const scheduling = {\n ...DEFAULT_SCHEDULING,\n ...(config.scheduling ?? {}),\n summaryTemplate:\n config.scheduling?.summaryTemplate ?? `${config.name}: introduction call with {{firstName}} {{lastName}}`,\n };\n const row: Record<string, unknown> = {\n id: config.id,\n name: config.name,\n standardPriceCents: prices?.standardCents ?? 0,\n foundingDiscountCents: prices?.foundingDiscountCents ?? 0,\n notificationEmail: emails?.notificationEmail ?? \"\",\n replyTo: emails?.replyTo ?? emails?.notificationEmail ?? \"\",\n disclaimerText: policy.disclaimerText ?? \"\",\n refundPolicyText: policy.refundPolicyText ?? \"\",\n trustCopy: policy.trustCopy ?? \"\",\n emailTemplates: emails?.templates ?? defaultEmailTemplates(config.name),\n schedulingJson: scheduling,\n };\n if (emails?.debugEmail) row.debugEmail = emails.debugEmail;\n if (policy.commitmentText) row.commitmentText = policy.commitmentText;\n if (policy.normsText) row.normsText = policy.normsText;\n return row;\n}\n","// Identity + authorization for a chapter/hub site — the pieces every membership\n// site needs and none should re-derive: a resolved role policy, role resolution\n// from a JWT claim, the privilege-escalation guard, and a tenant-vault read.\n// Everything here is pure or structural (no runtime @odla-ai/db import), so it is\n// trivially testable and the worker stays the only thing that talks to odla-db.\nimport type { ChapterAuth, ChapterMode, ResolvedAuth } from \"./types\";\n\n/**\n * Apply defaults + validate the auth config into a {@link ResolvedAuth}. Defaults\n * by mode: `chapter` → the `provisional/member/admin` claim ladder with the\n * `superAdmins` tier; `hub` → the `admins` allowlist table with no super tier.\n * Throws at import on a bad policy.\n */\nexport function resolveAuth(mode: ChapterMode, auth: ChapterAuth | undefined): ResolvedAuth {\n const a = auth ?? {};\n const source = a.source ?? (mode === \"hub\" ? \"table\" : \"claim\");\n if (source !== \"claim\" && source !== \"table\") {\n throw new Error(`defineChapter.auth.source: must be \"claim\" or \"table\" — got ${JSON.stringify(a.source)}`);\n }\n const claim = a.claim ?? \"role\";\n if (typeof claim !== \"string\" || claim === \"\") {\n throw new Error(\"defineChapter.auth.claim: must be a non-empty string\");\n }\n const ladder = a.ladder ?? [\"provisional\", \"member\", \"admin\"];\n if (!Array.isArray(ladder) || ladder.length === 0 || !ladder.every((r) => typeof r === \"string\" && r !== \"\")) {\n throw new Error(\"defineChapter.auth.ladder: must be a non-empty array of role strings\");\n }\n const adminRole = ladder[ladder.length - 1] as string;\n const superAdmins = a.superAdmins ?? source === \"claim\";\n return { source, claim, ladder, adminRole, superAdmins };\n}\n\n/** The role from a verified JWT payload, per the resolved policy. An unknown or\n * missing claim falls back to the lowest ladder rung (fail safe, never admin). */\nexport function roleFromClaim(payload: Record<string, unknown>, auth: ResolvedAuth): string {\n const raw = payload[auth.claim];\n return typeof raw === \"string\" && auth.ladder.includes(raw) ? raw : (auth.ladder[0] as string);\n}\n\n/** Does a role meet the admin bar (the highest ladder rung)? */\nexport function isAdminRole(role: string, auth: ResolvedAuth): boolean {\n return role === auth.adminRole;\n}\n\n/** Inputs to the role-change guard — resolved by the caller (route) from the\n * identity provider + the read-only `superAdmins` table. */\nexport interface RoleChangeContext {\n actorId: string;\n actorIsSuper: boolean;\n targetId: string;\n targetCurrentRole: string;\n targetIsSuper: boolean;\n newRole: string;\n auth: ResolvedAuth;\n}\n\n/** The result of {@link canChangeRole}: allow, or deny with the HTTP status +\n * message the route should return. */\nexport type GuardResult = { ok: true } | { ok: false; status: number; error: string };\n\n/**\n * The privilege-escalation guard — package-enforced so every site gets it and\n * none re-derives it. Denies: an out-of-ladder role; changing your own role;\n * touching a super-admin unless you are one; and (when a `superAdmins` tier\n * exists) creating or altering an admin unless you are a super-admin. Note the\n * super-admin tier itself is never writable here — it lives in the read-only\n * `superAdmins` table, set only in odla Studio.\n */\nexport function canChangeRole(ctx: RoleChangeContext): GuardResult {\n const { auth } = ctx;\n if (!auth.ladder.includes(ctx.newRole)) {\n return { ok: false, status: 400, error: `role must be one of: ${auth.ladder.join(\", \")}` };\n }\n if (ctx.actorId === ctx.targetId) {\n return { ok: false, status: 400, error: \"you cannot change your own role\" };\n }\n if (ctx.targetIsSuper && !ctx.actorIsSuper) {\n return { ok: false, status: 403, error: \"this person is a super-admin; their access is managed in odla Studio\" };\n }\n const touchesAdmin = ctx.newRole === auth.adminRole || ctx.targetCurrentRole === auth.adminRole;\n if (auth.superAdmins && touchesAdmin && !ctx.actorIsSuper) {\n return { ok: false, status: 403, error: `only super-admins can create or change an ${auth.adminRole}` };\n }\n return { ok: true };\n}\n\n/** Structural view of odla-db's tenant-vault read, so chapter takes no runtime\n * dependency on @odla-ai/db. The worker's admin client satisfies this. */\nexport interface SecretStore {\n secrets: { get(name: string): Promise<string> };\n}\n\n/**\n * Read a tenant-vault secret by name; `undefined` when it is absent or the vault\n * errors, so callers degrade gracefully (e.g. `paymentsReady: false`) rather than\n * throwing. Never logs the value.\n */\nexport async function getVaultSecret(db: SecretStore, name: string): Promise<string | undefined> {\n try {\n const value = await db.secrets.get(name);\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n } catch {\n return undefined;\n }\n}\n","// The application status pipeline — config, not code. Which statuses exist, which\n// a member can book an intro call from, and which an admin can approve from\n// differ per site; the one invariant every site wants is that status never moves\n// backwards. All of this is pure + tested here; the worker enforces it on every\n// status write, and the CRM record.stage mirrors application.status (never the\n// reverse). Defaults reproduce the proven membership pipeline exactly.\nimport type { ChapterPipeline, ResolvedPipeline } from \"./types\";\n\nconst DEFAULT_STAGES = [\n \"submitted\",\n \"paid_pending_vetting\",\n \"call_scheduled\",\n \"interviewed\",\n \"approved\",\n \"declined\",\n \"refunded\",\n] as const;\nconst DEFAULT_BOOKABLE = [\"submitted\", \"paid_pending_vetting\", \"call_scheduled\"] as const;\nconst DEFAULT_APPROVABLE = [\"paid_pending_vetting\", \"call_scheduled\", \"interviewed\"] as const;\n\n/**\n * Apply defaults + validate the pipeline config. With no config, the complete\n * reference pipeline. With `stages` given but the subsets omitted, the subsets\n * default to empty (a site opts in to bookable/approvable states explicitly).\n * Throws at import on a bad pipeline (empty/duplicate stages, an initial or a\n * subset entry not on the ladder).\n */\nexport function resolvePipeline(p: ChapterPipeline | undefined): ResolvedPipeline {\n const usingDefaults = !p?.stages;\n const stages = p?.stages ?? [...DEFAULT_STAGES];\n if (!Array.isArray(stages) || stages.length === 0 || !stages.every((s) => typeof s === \"string\" && s !== \"\")) {\n throw new Error(\"defineChapter.pipeline.stages: must be a non-empty array of status strings\");\n }\n if (new Set(stages).size !== stages.length) {\n throw new Error(\"defineChapter.pipeline.stages: statuses must be unique\");\n }\n const initial = p?.initial ?? (stages[0] as string);\n if (!stages.includes(initial)) {\n throw new Error(`defineChapter.pipeline.initial: \"${initial}\" is not one of the stages`);\n }\n const bookableFrom = p?.bookableFrom ?? (usingDefaults ? [...DEFAULT_BOOKABLE] : []);\n const approvableFrom = p?.approvableFrom ?? (usingDefaults ? [...DEFAULT_APPROVABLE] : []);\n for (const [name, subset] of [\n [\"bookableFrom\", bookableFrom],\n [\"approvableFrom\", approvableFrom],\n ] as const) {\n for (const s of subset) {\n if (!stages.includes(s)) throw new Error(`defineChapter.pipeline.${name}: \"${s}\" is not one of the stages`);\n }\n }\n return { stages, bookableFrom, approvableFrom, initial };\n}\n\n/** The ordinal of a status in the ladder, or -1 if unknown. */\nexport function stageIndex(status: string, p: ResolvedPipeline): number {\n return p.stages.indexOf(status);\n}\n\n/**\n * The status-never-moves-backwards invariant: a transition is allowed only when\n * both statuses are on the ladder and `to` is at or ahead of `from`. The worker\n * calls this before every status write; a violation is a 409, never a silent\n * downgrade.\n */\nexport function canTransition(from: string, to: string, p: ResolvedPipeline): boolean {\n const fi = p.stages.indexOf(from);\n const ti = p.stages.indexOf(to);\n return fi >= 0 && ti >= 0 && ti >= fi;\n}\n\n/** May an intro call be booked from this status? */\nexport function canBook(status: string, p: ResolvedPipeline): boolean {\n return p.bookableFrom.includes(status);\n}\n\n/** May an application be approved (→ member) from this status? */\nexport function canApprove(status: string, p: ResolvedPipeline): boolean {\n return p.approvableFrom.includes(status);\n}\n","import type { ChapterCopy } from \"./copy.js\";\n\nexport const DEFAULT_ADMIN_COPY: ChapterCopy[\"admin\"] = {\n auth: {\n checking: \"Checking access…\",\n notAuthorized: \"Not authorized\",\n accountNotAuthorized: \"{account} isn't on the admin list.\",\n thisAccount: \"This account\",\n signOut: \"Sign out\",\n loading: \"Loading…\",\n signInNotConfigured: \"Sign-in not configured\",\n missingPublishableKey: \"No Clerk publishable key is set for this environment yet.\",\n noWorkspaces: \"No admin workspaces are configured.\",\n signInTagline: \"Admin sign-in, invite only\",\n },\n shell: {\n adminRole: \"admin\",\n adminConsole: \"Admin Console\",\n adminName: \"Admin\",\n navigationLabel: \"Admin navigation\",\n },\n workspaces: {\n dashboard: \"Dashboard\",\n overview: \"Overview\",\n billing: \"Billing\",\n people: \"People\",\n admission: \"Admission\",\n network: \"Network\",\n portfolio: \"Portfolio\",\n settings: \"Settings\",\n calendar: \"Calendar\",\n email: \"Email\",\n chapters: \"Chapters\",\n formations: \"Formation applications\",\n dealFlow: \"Deal flow\",\n dashboardViewsLabel: \"Dashboard views\",\n settingsViewsLabel: \"Settings views\",\n collectionsLabel: \"CRM collections\",\n portfolioViewsLabel: \"Portfolio views\",\n },\n dashboard: {\n loading: \"Loading dashboard…\",\n loadFailed: \"Couldn't load the dashboard\",\n upcomingCalls: \"Upcoming calls\",\n callsNeedAttention: \"{count} need attention\",\n noUpcomingCalls: \"No upcoming calls.\",\n drift: \"drift\",\n open: \"Open\",\n meet: \"Meet\",\n applications: \"Applications\",\n newMembers: \"New members\",\n newMembersUnavailable: \"Appears once billing is connected.\",\n revenueAdded: \"Revenue · annual run rate added\",\n revenue: \"Revenue\",\n revenueUnavailable: \"Appears once billing is connected.\",\n pipeline: \"Pipeline\",\n pipelineLabel: \"Membership pipeline\",\n thisWeek: \"+{count} this week\",\n noChange: \"no change\",\n activeMemberships: \"Active memberships\",\n annualRunRate: \"Annual run rate\",\n testMode: \"test mode\",\n },\n billing: {\n loading: \"Loading…\",\n loadFailed: \"Couldn't load billing\",\n notConfigured: \"Billing isn't configured. No Stripe key is vaulted for this group.\",\n active: \"Active\",\n annualized: \"Annualized\",\n renewingSoon: \"Renewing within 60 days\",\n pastDue: \"Past due\",\n subscriptions: \"Subscriptions\",\n testMode: \"Stripe test mode\",\n truncated: \"Showing the first 100 subscriptions. The list is truncated.\",\n name: \"Name\",\n email: \"Email\",\n application: \"Application\",\n subscription: \"Subscription\",\n cancelling: \"cancelling\",\n amount: \"Amount\",\n renews: \"Renews\",\n },\n availability: {\n loading: \"Loading…\",\n loadFailed: \"Couldn't load availability\",\n saved: \"Saved.\",\n title: \"Booking availability\",\n days: \"Days\",\n startHour: \"Start hour (0–24)\",\n endHour: \"End hour (0–24)\",\n slotMinutes: \"Slot length (minutes)\",\n minNoticeHours: \"Minimum notice (hours)\",\n windowDays: \"Booking window (days)\",\n timezone: \"Timezone\",\n summaryTemplate: \"Event summary template\",\n save: \"Save availability\",\n dayLabels: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\n },\n email: {\n loading: \"Loading…\",\n loadFailed: \"Couldn't load email config\",\n saved: \"Saved.\",\n sent: \"Sent {template} to {address}{redirected}.\",\n testFailed: \"Test send did not deliver.\",\n delivery: \"Delivery\",\n notificationAddress: \"Notification address\",\n replyTo: \"Reply-to\",\n debugInbox: \"Debug inbox\",\n debugInboxHint: \"Non-production sends redirect here.\",\n sendTest: \"Send test\",\n enabled: \"Enabled\",\n subject: \"Subject\",\n body: \"Body\",\n save: \"Save changes\",\n sendLog: \"Send log\",\n sentColumn: \"Sent\",\n templateColumn: \"Template\",\n statusColumn: \"Status\",\n toColumn: \"To\",\n failed: \"failed\",\n redirected: \"redirected\",\n delivered: \"delivered\",\n },\n meetings: {\n loading: \"Loading…\",\n loadFailed: \"Couldn't load meetings\",\n cancelConfirm: \"Cancel this call? The calendar provider notifies the attendee.\",\n newStartPrompt: \"New start time (for example, 2026-08-01 14:00):\",\n parseFailed: \"Couldn't parse that time.\",\n agenda: \"Agenda\",\n empty: \"No meetings.\",\n unknown: \"(unknown)\",\n drift: \"drift\",\n meet: \"Meet\",\n reschedule: \"Reschedule\",\n cancel: \"Cancel\",\n },\n admission: {\n title: \"Interview decisions\",\n description: \"Local decisions override Parent decisions. Requiring an interview locally suppresses a Parent waiver for the same email.\",\n email: \"Email\",\n decision: \"Decision\",\n expires: \"Expires\",\n note: \"Internal note\",\n waive: \"Waive interview\",\n require: \"Require interview\",\n add: \"Add decision\",\n ledger: \"Effective grant ledger\",\n loading: \"Loading…\",\n consumed: \"consumed\",\n revoked: \"revoked\",\n expired: \"expired\",\n active: \"active\",\n local: \"local\",\n parent: \"Parent\",\n revoke: \"Revoke\",\n },\n network: {\n title: \"Share to a follower\",\n allowlistDescription: \"Sends the target's allowlisted fields. Its pipeline and account state remain local.\",\n sharing: \"Sharing…\",\n shareWith: \"Share with {target}\",\n shared: \"Shared with {target}.\",\n shareFailed: \"Could not share with {target}.\",\n deliveryFailed: \"Delivery failed.\",\n loadingRollup: \"Loading network overview…\",\n loadRollupFailed: \"Couldn't load the network overview\",\n overview: \"Network overview\",\n configuredFollowers: \"Configured followers\",\n reachableFollowers: \"Reachable followers\",\n recordsAcrossFollowers: \"Records across followers\",\n noFollowers: \"No follower sites are configured.\",\n followers: \"Followers\",\n available: \"available\",\n unavailable: \"unavailable\",\n recordTotals: \"Portfolio records\",\n noRecordTotals: \"No aggregate records are available yet.\",\n },\n records: {\n workflowMissing: \"This record is not linked to an application workflow.\",\n comms: \"Comms\",\n commsHistory: \"Comms history\",\n scheduling: \"Scheduling\",\n billing: \"Billing\",\n notes: \"Notes\",\n access: \"Access\",\n sharing: \"Sharing\",\n lifecycle: \"Access & lifecycle\",\n role: \"Role\",\n superAdminHint: \"Super-admin, managed in odla Studio.\",\n noAccount: \"No linked account yet. The role is set once they sign in.\",\n approve: \"Approve\",\n refund: \"Refund\",\n approved: \"Approved.\",\n refunded: \"Refund issued.\",\n roleSet: \"Role set to {role}.\",\n messageSent: \"Message sent.\",\n messageNotSent: \"Message was not sent.\",\n loadingTemplates: \"Loading templates…\",\n template: \"Template\",\n chooseTemplate: \"Choose a template…\",\n sending: \"Sending…\",\n send: \"Send\",\n noMessages: \"No messages recorded.\",\n message: \"Message\",\n newStartPrompt: \"New start time:\",\n parseFailed: \"Couldn't parse that time.\",\n cancelConfirm: \"Cancel this call?\",\n callCancelled: \"Call cancelled.\",\n callRescheduled: \"Call rescheduled.\",\n noApplication: \"No application is linked to this record.\",\n loadingMeetings: \"Loading meetings…\",\n noMeetings: \"No meetings recorded.\",\n joinMeeting: \"Join meeting\",\n openCalendar: \"Open calendar\",\n reschedule: \"Reschedule\",\n cancel: \"Cancel\",\n },\n};\n","import type { ChapterCopy } from \"./copy.js\";\n\nexport const DEFAULT_COMMON_COPY: ChapterCopy[\"common\"] = {\n loading: \"Loading…\",\n saved: \"Saved.\",\n unknown: \"(unknown)\",\n};\n\nexport const DEFAULT_JOIN_COPY: ChapterCopy[\"join\"] = {\n form: {\n submit: \"Submit application\",\n submitting: \"Submitting…\",\n submitFailed: \"Your application could not be submitted.\",\n unexpectedFailure: \"Something went wrong. Please try again.\",\n },\n booking: {\n unavailable: \"Scheduling is briefly unavailable. We'll reach out by email to arrange your call.\",\n loadFailed: \"Times are briefly unavailable. Please try again.\",\n slotTaken: \"That time was just taken. Here are the current openings.\",\n failed: \"The booking could not be completed.\",\n loading: \"Loading available times…\",\n book: \"Book this time\",\n booking: \"Booking…\",\n },\n payment: {\n setupFailed: \"Payment could not be set up. Please try again.\",\n preparing: \"Preparing secure payment…\",\n pending: \"Confirming your payment…\",\n processing: \"Processing…\",\n payAndContinue: \"Pay and continue\",\n incomplete: \"The payment did not complete. Please try again.\",\n consent: \"I have read and agree to the pricing and refund policy above.\",\n },\n done: {\n label: \"You're booked\",\n calendarInvite: \"A calendar invitation with the video call link is on its way to your email.\",\n memberArea: \"Go to your member area\",\n },\n accepted: {\n label: \"You're approved\",\n body: \"Your membership is approved. No introduction call is required.\",\n },\n gift: {\n chooseSelf: \"Buy membership for myself\",\n optionsLabel: \"Or give access to someone else\",\n label: \"Your gift code\",\n body: \"Share this one-time code with the recipient. It becomes active after payment is confirmed.\",\n save: \"Save it now. For security, this code is shown only once.\",\n rotate: \"Generate a new code\",\n rotateFailed: \"A new code could not be generated.\",\n },\n};\n\nexport const DEFAULT_MEMBERS_COPY: ChapterCopy[\"members\"] = {\n loadFailed: \"Sign in is briefly unavailable. Please refresh.\",\n account: {\n signOut: \"Sign out\",\n adminConsole: \"Admin console\",\n },\n provisional: {\n cardLabel: \"Your Application\",\n applicationNeeded: \"One step remains\",\n applicationNeededBody: \"Your account is ready, and the application that completes it takes a few minutes.\",\n apply: \"Apply for membership\",\n refunded: \"Membership refunded\",\n refundedBody: \"Your fee has been refunded in full and your membership is canceled.\",\n active: \"Your membership is active.\",\n renews: \"Your membership is active and renews {date}.\",\n introductionCall: \"Your introduction call\",\n calendarInvite: \"A calendar invitation with the video call link is in your email.\",\n joinCall: \"Join the video call\",\n bookCall: \"Book your introduction call\",\n bookCallBody: \"Your application is in. Choose a time below, and a calendar invitation will reach your email.\",\n chooseTime: \"Choose a time\",\n },\n full: {\n welcome: \"Welcome back.\",\n },\n gifts: {\n title: \"Give access\",\n body: \"Purchase access for someone else and share the one-time claim code.\",\n noneAvailable: \"No gift options are available right now.\",\n paid: \"Payment submitted. Save the code below while it is visible.\",\n saveCode: \"This code is shown once. Save it before leaving this page.\",\n purchases: \"Your gifts\",\n noPurchases: \"No gift purchases yet.\",\n pending: \"Pending\",\n redeemed: \"Redeemed\",\n expired: \"Expired\",\n revoked: \"Revoked\",\n rotate: \"Rotate code\",\n rotated: \"A new code was generated. Save it now.\",\n rotateFailed: \"The code could not be rotated.\",\n redeemTitle: \"Redeem a gift\",\n code: \"One-time code\",\n redeem: \"Redeem\",\n redeemFailed: \"The code is invalid or unavailable.\",\n },\n reschedule: {\n changeTime: \"Change your time\",\n unavailable: \"Scheduling is briefly unavailable. We'll reach out by email to arrange your call.\",\n loadFailed: \"Times are briefly unavailable. Please try again.\",\n slotGone: \"That time is no longer available. Please pick another.\",\n loading: \"Loading available times…\",\n noTimes: \"No open times right now. Please check back soon.\",\n rescheduling: \"Rescheduling…\",\n keepTime: \"Keep my current time\",\n },\n};\n","import { DEFAULT_ADMIN_COPY } from \"./copy-defaults-admin.js\";\nimport {\n DEFAULT_COMMON_COPY,\n DEFAULT_JOIN_COPY,\n DEFAULT_MEMBERS_COPY,\n} from \"./copy-defaults.js\";\nimport type { ChapterCopy, ChapterCopyInput } from \"./copy.js\";\n\n/** Complete default language resolved beneath partial Chapter copy overrides. */\nexport const DEFAULT_CHAPTER_COPY: ChapterCopy = {\n common: DEFAULT_COMMON_COPY,\n join: DEFAULT_JOIN_COPY,\n members: DEFAULT_MEMBERS_COPY,\n admin: DEFAULT_ADMIN_COPY,\n};\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n\nfunction mergeCopy<T>(base: T, input: unknown, path: string): T {\n if (typeof base === \"string\") {\n if (input === undefined) return base;\n if (typeof input !== \"string\") throw new Error(`${path}: must be a string`);\n return input as T;\n }\n if (Array.isArray(base)) {\n if (input === undefined) return [...base] as T;\n if (!Array.isArray(input) || !input.every((item) => typeof item === \"string\")) {\n throw new Error(`${path}: must be an array of strings`);\n }\n return [...input] as T;\n }\n if (!isObject(base)) return base;\n if (input !== undefined && !isObject(input)) throw new Error(`${path}: must be an object`);\n const overrides = input as Record<string, unknown> | undefined;\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(base)) {\n result[key] = mergeCopy(value, overrides?.[key], `${path}.${key}`);\n }\n return result as T;\n}\n\n/** Resolve a partial copy contract and validate every supplied leaf. */\nexport function resolveChapterCopy(input?: ChapterCopyInput): ChapterCopy {\n return mergeCopy(DEFAULT_CHAPTER_COPY, input, \"defineChapter.copy\");\n}\n\n/** Replace `{name}` placeholders without interpreting the resulting text as HTML. */\nexport function formatChapterCopy(\n template: string,\n values: Readonly<Record<string, string | number>>,\n): string {\n return template.replace(/\\{([a-zA-Z][a-zA-Z0-9]*)\\}/g, (match, key: string) =>\n Object.prototype.hasOwnProperty.call(values, key) ? String(values[key]) : match,\n );\n}\n","import type { Crm, FieldConditions, FieldDef, FieldType } from \"@odla-ai/crm\";\nimport type { Chapter, ResolvedApplication, ResolvedLeaderFormation } from \"./types\";\n\n/** Current public schema version for Chapter flow-field contracts. */\nexport const CHAPTER_FLOW_FIELDS_SCHEMA_VERSION = 1 as const;\n\n/** Configurable Chapter intake journeys that publish field contracts. */\nexport type ChapterFieldFlow = \"join\" | \"formation\";\n\n/** Email comparison policy advertised by an email field. */\nexport type ChapterEmailIdentity = \"literal\";\n\n/**\n * One effective field in a Chapter intake journey.\n *\n * IDs, value types, and options come from the follower-declared schema. A hub\n * or CMS may select, order, and configure only those declared fields; it cannot\n * use this presentation document to add storage or widen follower authority.\n */\nexport interface ChapterFlowField {\n id: string;\n label: string;\n type: FieldType;\n required: boolean;\n order: number;\n maxLength?: number;\n options?: readonly string[];\n conditions?: FieldConditions;\n /** Present only for an email identity field. Aliases such as `+tag` remain significant. */\n emailIdentity?: ChapterEmailIdentity;\n}\n\n/** Ordered, versioned effective field state for one Chapter journey. */\nexport interface ChapterFlowFieldContract {\n schemaVersion: typeof CHAPTER_FLOW_FIELDS_SCHEMA_VERSION;\n flow: ChapterFieldFlow;\n fields: readonly ChapterFlowField[];\n}\n\nconst APPLICATION_LABELS: Readonly<Record<string, string>> = {\n firstName: \"First name\",\n lastName: \"Last name\",\n email: \"Email\",\n referral: \"Referral source\",\n referralName: \"Referral name\",\n whoYouAre: \"Who you are\",\n linkedin: \"LinkedIn\",\n message: \"Intro message\",\n phone: \"Phone\",\n state: \"State\",\n};\n\nfunction humanize(id: string): string {\n const text = id.replace(/([a-z0-9])([A-Z])/g, \"$1 $2\").replace(/[_-]+/g, \" \").trim();\n return text ? `${text[0]!.toUpperCase()}${text.slice(1)}` : id;\n}\n\nfunction applicationDefs(chapter: Chapter): Record<string, FieldDef> {\n try {\n return chapter.crm.type(\"person\").fields;\n } catch {\n return {};\n }\n}\n\nfunction applicationType(id: string, def: FieldDef | undefined): FieldType {\n // Application rows accept configurable strings. Preserve the richer\n // string-like CRM hints without claiming that a numeric/date/json CRM field\n // changes the application storage contract.\n if (def && [\"string\", \"email\", \"url\", \"enum\"].includes(def.type)) return def.type;\n return id === \"email\" ? \"email\" : id === \"linkedin\" ? \"url\" : \"string\";\n}\n\n/** Resolve the exact ordered fields accepted by the membership application flow. */\nexport function applicationFlowFields(\n chapter: Chapter,\n application: ResolvedApplication = chapter.application,\n): ChapterFlowField[] {\n const defs = applicationDefs(chapter);\n return [...application.required, ...application.optional].map((id, order) => {\n const def = defs[id];\n const conditions = application.conditions[id];\n const type = applicationType(id, def);\n return {\n id,\n label: def?.label ?? APPLICATION_LABELS[id] ?? humanize(id),\n type,\n required: application.required.includes(id),\n order,\n maxLength: application.maxLen[id] ?? application.defaultMaxLen,\n ...(type === \"enum\" && def?.options ? { options: [...def.options] } : {}),\n ...(conditions ? { conditions: { ...conditions } } : {}),\n ...(type === \"email\" ? { emailIdentity: \"literal\" as const } : {}),\n };\n });\n}\n\n/** Common resolver retained separately so the legacy formationFields helper cannot drift. */\nexport function resolveFormationFlowFields(\n crm: Crm,\n formation: ResolvedLeaderFormation,\n): ChapterFlowField[] {\n if (!formation.enabled) return [];\n const def = crm.type(formation.type);\n return [...formation.required, ...formation.optional].map((id, order) => {\n const field = def.fields[id]!;\n return {\n id,\n label: field.label ?? humanize(id),\n type: field.type,\n required: formation.required.includes(id),\n order,\n maxLength: formation.maxLen[id] ?? formation.defaultMaxLen,\n ...(field.options ? { options: [...field.options] } : {}),\n ...(id === def.emailField || field.type === \"email\" ? { emailIdentity: \"literal\" as const } : {}),\n };\n });\n}\n\n/** Resolve the exact ordered fields accepted by the chapter-formation flow. */\nexport function formationFlowFields(\n chapter: Chapter,\n formation: ResolvedLeaderFormation = chapter.formation,\n): ChapterFlowField[] {\n return resolveFormationFlowFields(chapter.crm, formation);\n}\n\n/**\n * Build the public field contract consumed by follower forms and CMS previews.\n * The optional application is the already-authorized effective selection from\n * signup control; it never expands the follower's declared application schema.\n */\nexport function chapterFlowFieldContract(\n chapter: Chapter,\n flow: ChapterFieldFlow,\n application: ResolvedApplication = chapter.application,\n): ChapterFlowFieldContract {\n return {\n schemaVersion: CHAPTER_FLOW_FIELDS_SCHEMA_VERSION,\n flow,\n fields: flow === \"join\"\n ? applicationFlowFields(chapter, application)\n : formationFlowFields(chapter),\n };\n}\n","import type { Crm } from \"@odla-ai/crm\";\nimport type { LeaderFormationConfig, ResolvedLeaderFormation } from \"./types\";\nimport { resolveFormationFlowFields } from \"./flow-fields\";\n\nconst DEFAULT_REQUIRED = [\"name\", \"email\", \"location\", \"thesis\"];\nconst DEFAULT_OPTIONAL = [\"proposedChapter\", \"experience\", \"collaborators\"];\n\n/** Resolve and validate the public chapter-formation intake contract. */\nexport function resolveLeaderFormation(\n input: LeaderFormationConfig | undefined,\n crm: Crm,\n): ResolvedLeaderFormation {\n const type = input?.type ?? \"chapter_application\";\n if (!input) {\n return {\n enabled: false,\n type,\n required: [],\n optional: [],\n maxLen: {},\n defaultMaxLen: 4000,\n bodyCap: 32768,\n };\n }\n const def = crm.config.types[type];\n if (!def) throw new Error(`defineChapter.formation.type: unknown CRM type \"${type}\"`);\n const required = input.required ?? (type === \"chapter_application\" ? DEFAULT_REQUIRED : []);\n const optional = input.optional ?? (type === \"chapter_application\" ? DEFAULT_OPTIONAL : []);\n for (const [name, values] of [[\"required\", required], [\"optional\", optional]] as const) {\n if (!Array.isArray(values) || !values.every((field) => typeof field === \"string\" && field !== \"\")) {\n throw new Error(`defineChapter.formation.${name}: must be an array of field-name strings`);\n }\n }\n const duplicates = [...required, ...optional].filter((field, index, fields) => fields.indexOf(field) !== index);\n if (duplicates.length) throw new Error(`defineChapter.formation: duplicate public field \"${duplicates[0]}\"`);\n const unknown = [...required, ...optional].filter((field) => !def.fields[field]);\n if (unknown.length) throw new Error(`defineChapter.formation: field \"${unknown[0]}\" is not declared on CRM type \"${type}\"`);\n const missingRequired = Object.entries(def.fields)\n .filter(([, field]) => field.required)\n .map(([field]) => field)\n .filter((field) => !required.includes(field));\n if (missingRequired.length) {\n throw new Error(`defineChapter.formation.required: must include required CRM field \"${missingRequired[0]}\"`);\n }\n const unsupportedRequired = required.find((field) =>\n ![\"string\", \"email\", \"url\", \"enum\"].includes(def.fields[field]!.type));\n if (unsupportedRequired) {\n throw new Error(`defineChapter.formation.required: field \"${unsupportedRequired}\" must be string-like`);\n }\n if (required.length === 0) throw new Error(\"defineChapter.formation.required: must not be empty\");\n const defaultMaxLen = input.defaultMaxLen ?? 4000;\n const bodyCap = input.bodyCap ?? 32768;\n if (!Number.isSafeInteger(defaultMaxLen) || defaultMaxLen < 1 || defaultMaxLen > 32768) {\n throw new Error(\"defineChapter.formation.defaultMaxLen: must be an integer from 1 to 32768\");\n }\n if (!Number.isSafeInteger(bodyCap) || bodyCap < 1024 || bodyCap > 131072) {\n throw new Error(\"defineChapter.formation.bodyCap: must be an integer from 1024 to 131072\");\n }\n for (const [field, cap] of Object.entries(input.maxLen ?? {})) {\n if (![...required, ...optional].includes(field) || !Number.isSafeInteger(cap) || cap < 1 || cap > 32768) {\n throw new Error(`defineChapter.formation.maxLen.${field}: must name a public field and be an integer from 1 to 32768`);\n }\n }\n return {\n enabled: true,\n type,\n required,\n optional,\n maxLen: input.maxLen ?? {},\n defaultMaxLen,\n bodyCap,\n };\n}\n\n/** Public, presentational field metadata for a host-owned intake form. */\nexport function formationFields(\n crm: Crm,\n formation: ResolvedLeaderFormation,\n): import(\"./flow-fields\").ChapterFlowField[] {\n return resolveFormationFlowFields(crm, formation);\n}\n","import type { Crm } from \"@odla-ai/crm\";\nimport type {\n ChapterConfig,\n ResolvedNetwork,\n ResolvedNetworkReader,\n ResolvedNetworkTarget,\n} from \"./types\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst FIELD = /^[a-z][a-zA-Z0-9_]*$/;\nconst BINDING = /^[A-Z][A-Z0-9_]{0,127}$/;\n\nfunction validateSharedNotes(opts: {\n path: string;\n values: readonly string[];\n crm: Crm;\n fields?: Record<string, readonly string[]>;\n}) {\n const duplicate = opts.values.some((type, index) => opts.values.indexOf(type) !== index);\n const invalid = opts.values.some((type) =>\n !FIELD.test(type) || !opts.crm.config.types[type] || (opts.fields ? !opts.fields[type] : false));\n if (duplicate || invalid) {\n throw new Error(`${opts.path}: must contain unique CRM types allowed by fields`);\n }\n}\n\n/** Resolve the two-sided federation contract. Targets are leader-owned\n * outbound policy; readers are follower-owned disclosure/write policy. */\nexport function resolveNetwork(config: ChapterConfig, crm: Crm): ResolvedNetwork {\n const seen = new Set<string>();\n const targets: ResolvedNetworkTarget[] = [];\n for (const target of config.network?.targets ?? []) {\n if (!SLUG.test(target.id)) {\n throw new Error(`defineChapter.network.targets.id: must be a lowercase slug — got ${JSON.stringify(target.id)}`);\n }\n if (seen.has(target.id)) throw new Error(`defineChapter.network.targets: duplicate target \"${target.id}\"`);\n seen.add(target.id);\n let url: URL;\n try {\n url = new URL(target.url);\n } catch {\n throw new Error(`defineChapter.network.targets.${target.id}.url: must be an absolute URL`);\n }\n const local = url.hostname === \"localhost\" || url.hostname === \"127.0.0.1\" || url.hostname === \"::1\";\n if (url.protocol !== \"https:\" && !(local && url.protocol === \"http:\")) {\n throw new Error(`defineChapter.network.targets.${target.id}.url: must use https (http is allowed only for localhost)`);\n }\n const fields = target.fields;\n for (const [type, names] of Object.entries(fields ?? {})) {\n if (!FIELD.test(type) || names.length === 0 || names.some((name) => !FIELD.test(name))) {\n throw new Error(\n `defineChapter.network.targets.${target.id}.fields.${type}: type and field names must be non-empty CRM identifiers`,\n );\n }\n const def = crm.config.types[type];\n if (!def) throw new Error(`defineChapter.network.targets.${target.id}.fields: unknown leader CRM type \"${type}\"`);\n const unknown = names.filter((field) => !def.fields[field]);\n if (unknown.length > 0) {\n throw new Error(\n `defineChapter.network.targets.${target.id}.fields.${type}: ${unknown.map((field) => `\"${field}\"`).join(\", \")} ` +\n \"not declared on the leader CRM type\",\n );\n }\n const nameField = def.nameField ?? \"name\";\n if (!names.includes(nameField)) {\n throw new Error(\n `defineChapter.network.targets.${target.id}.fields.${type}: must include required name field \"${nameField}\"`,\n );\n }\n }\n const secretName = target.secretName?.trim() || `network_share_${target.id.replaceAll(\"-\", \"_\")}`;\n if (!/^[a-zA-Z][a-zA-Z0-9_-]{1,127}$/.test(secretName)) {\n throw new Error(`defineChapter.network.targets.${target.id}.secretName: must be a vault-key identifier`);\n }\n const binding = target.binding?.trim();\n if (binding && !BINDING.test(binding)) {\n throw new Error(\n `defineChapter.network.targets.${target.id}.binding: must be an uppercase Worker binding identifier`,\n );\n }\n const sharedNotes = target.sharedNotes ?? [];\n validateSharedNotes({\n path: `defineChapter.network.targets.${target.id}.sharedNotes`,\n values: sharedNotes,\n crm,\n fields,\n });\n targets.push({\n id: target.id,\n name: target.name?.trim() || target.id,\n url: url.origin,\n ...(binding ? { binding } : {}),\n secretName,\n ...(fields ? { fields } : {}),\n sharedNotes,\n });\n }\n const readerIds = new Set<string>();\n const readers: ResolvedNetworkReader[] = [];\n for (const reader of config.network?.readers ?? []) {\n if (!SLUG.test(reader.id)) {\n throw new Error(`defineChapter.network.readers.id: must be a lowercase slug — got ${JSON.stringify(reader.id)}`);\n }\n if (readerIds.has(reader.id)) {\n throw new Error(`defineChapter.network.readers: duplicate reader \"${reader.id}\"`);\n }\n readerIds.add(reader.id);\n const entries = Object.entries(reader.fields ?? {});\n if (entries.length === 0) {\n throw new Error(`defineChapter.network.readers.${reader.id}.fields: at least one CRM type is required`);\n }\n for (const [type, names] of entries) {\n if (!FIELD.test(type) || names.length === 0 || names.some((name) => !FIELD.test(name))) {\n throw new Error(\n `defineChapter.network.readers.${reader.id}.fields.${type}: type and field names must be non-empty CRM identifiers`,\n );\n }\n const def = crm.config.types[type];\n if (!def) {\n throw new Error(`defineChapter.network.readers.${reader.id}.fields: unknown local CRM type \"${type}\"`);\n }\n const unknown = names.filter((field) => !def.fields[field]);\n if (unknown.length > 0) {\n throw new Error(\n `defineChapter.network.readers.${reader.id}.fields.${type}: ` +\n `${unknown.map((field) => `\"${field}\"`).join(\", \")} not declared on the local CRM type`,\n );\n }\n const nameField = def.nameField ?? \"name\";\n if (!names.includes(nameField)) {\n throw new Error(\n `defineChapter.network.readers.${reader.id}.fields.${type}: must include required name field \"${nameField}\"`,\n );\n }\n }\n const sharedNotes = reader.sharedNotes ?? [];\n validateSharedNotes({\n path: `defineChapter.network.readers.${reader.id}.sharedNotes`,\n values: sharedNotes,\n crm,\n fields: reader.fields,\n });\n readers.push({ id: reader.id, fields: reader.fields, sharedNotes });\n }\n return { targets, readers };\n}\n","import type { ChapterSignupControl, ResolvedSignupControl } from \"./types-signup-control\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst SECRET_NAME = /^[a-z][a-z0-9_]{1,127}$/;\n\n/** Validate one deliberately separate signup-control edge. */\nexport function resolveSignupControl(\n input: ChapterSignupControl | undefined,\n): ResolvedSignupControl | null {\n if (!input) return null;\n if (!SLUG.test(input.sourceId)) {\n throw new Error(\"defineChapter.signupControl.sourceId: must be a lowercase app slug\");\n }\n if (input.stripeMode !== \"test\" && input.stripeMode !== \"live\") {\n throw new Error('defineChapter.signupControl.stripeMode: must be \"test\" or \"live\"');\n }\n const secretName = input.secretName?.trim() || \"signup_control_secret\";\n if (!SECRET_NAME.test(secretName)) {\n throw new Error(\"defineChapter.signupControl.secretName: must be a vault-key identifier\");\n }\n return { sourceId: input.sourceId, secretName, stripeMode: input.stripeMode };\n}\n","import type { ChapterMemberContent, ResolvedMemberContent } from \"./types-member-content\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst SECRET_NAME = /^[a-z][a-z0-9_]{1,127}$/;\n\n/** Validate the deliberately separate member-content authoring boundary. */\nexport function resolveMemberContent(input: ChapterMemberContent | undefined): ResolvedMemberContent | null {\n if (!input) return null;\n const parent = input.parent;\n if (parent && !SLUG.test(parent.sourceId)) {\n throw new Error(\"defineChapter.memberContent.parent.sourceId: must be a lowercase app slug\");\n }\n const secretName = parent?.secretName?.trim() || \"member_content_control_secret\";\n if (parent && !SECRET_NAME.test(secretName)) {\n throw new Error(\"defineChapter.memberContent.parent.secretName: must be a vault-key identifier\");\n }\n return {\n enabled: true,\n localAuthoring: input.localAuthoring !== false,\n parent: parent ? { sourceId: parent.sourceId, secretName } : null,\n };\n}\n","// Reusable CRM records for a leader that forms and operates a portfolio of\n// chapters. This is configuration, not a second data engine: every record still\n// uses @odla-ai/crm's normal CRUD, pipelines, activities, views, and relations.\nimport { composeCrmConfigs, type CrmConfig, type TypeDef } from \"@odla-ai/crm\";\nimport { defaultCrm } from \"./defaults\";\n\n/** Options for {@link leaderCrmConfig}. */\nexport interface LeaderCrmOptions {\n /** Existing host CRM config to preserve. Defaults to Chapter's people +\n * businesses graph for hub mode. */\n base?: CrmConfig;\n /** Host-owned additions or replacements for the durable chapter record.\n * Fields and facets merge with the preset; a supplied pipeline replaces the\n * generic proposed/forming/active lifecycle. The final composed CRM still\n * goes through defineCrm's normal validation. */\n chapter?: Partial<TypeDef>;\n}\n\n/**\n * Add generic chapter-formation, portfolio, and deal-flow records to an\n * existing CRM. Collisions fail through `composeCrmConfigs`, so this preset\n * never silently replaces a host's people pipeline or templates.\n */\nexport function leaderCrmConfig(options: LeaderCrmOptions = {}): CrmConfig {\n const base = options.base ?? defaultCrm(\"hub\");\n const defaultChapter: TypeDef = {\n label: \"Chapter\",\n labelPlural: \"Chapters\",\n workspace: \"portfolio\",\n nameField: \"name\",\n fields: {\n name: { type: \"string\", label: \"Name\", required: true },\n slug: { type: \"string\", label: \"Slug\", slot: \"s1\" },\n region: { type: \"string\", label: \"Region\", slot: \"s2\" },\n url: { type: \"url\", label: \"Website\" },\n thesis: { type: \"string\", label: \"Investment thesis\" },\n launchedAt: { type: \"date\", label: \"Launch date\", slot: \"d1\" },\n notes: { type: \"string\", label: \"Notes\" },\n },\n pipeline: {\n stages: [\n { id: \"proposed\", label: \"Proposed\" },\n { id: \"forming\", label: \"Forming\" },\n { id: \"active\", label: \"Active\" },\n { id: \"paused\", label: \"Paused\" },\n { id: \"closed\", label: \"Closed\", terminal: true },\n ],\n transitions: {\n proposed: [\"forming\", \"closed\"],\n forming: [\"active\", \"paused\", \"closed\"],\n active: [\"paused\", \"closed\"],\n paused: [\"forming\", \"active\", \"closed\"],\n },\n },\n facets: { rank: \"manual\" },\n };\n const chapterOverride = options.chapter ?? {};\n const chapterType: TypeDef = {\n ...defaultChapter,\n ...chapterOverride,\n fields: {\n ...defaultChapter.fields,\n ...(chapterOverride.fields ?? {}),\n // The preset's natural identity is not optional even when the host adds\n // its own fields or relabels the name input.\n name: {\n ...defaultChapter.fields.name,\n ...(chapterOverride.fields?.name ?? {}),\n type: \"string\",\n required: true,\n },\n },\n facets: {\n ...defaultChapter.facets,\n ...(chapterOverride.facets ?? {}),\n },\n };\n const portfolio: CrmConfig = {\n types: {\n chapter: chapterType,\n chapter_application: {\n label: \"Chapter application\",\n labelPlural: \"Formation applications\",\n workspace: \"portfolio\",\n nameField: \"name\",\n emailField: \"email\",\n fields: {\n name: { type: \"string\", label: \"Applicant name\", required: true },\n email: { type: \"email\", label: \"Email\", required: true },\n location: { type: \"string\", label: \"Location\", required: true, slot: \"s1\" },\n proposedChapter: { type: \"string\", label: \"Proposed chapter\", slot: \"s2\" },\n thesis: { type: \"string\", label: \"Proposed thesis\", required: true },\n experience: { type: \"string\", label: \"Relevant experience\" },\n collaborators: { type: \"json\", label: \"Collaborators\" },\n notes: { type: \"string\", label: \"Internal notes\" },\n },\n pipeline: {\n stages: [\n { id: \"submitted\", label: \"Submitted\" },\n { id: \"reviewing\", label: \"Reviewing\" },\n { id: \"interviewing\", label: \"Interviewing\" },\n { id: \"approved\", label: \"Approved\" },\n { id: \"forming\", label: \"Forming\" },\n { id: \"declined\", label: \"Declined\", terminal: true },\n ],\n transitions: {\n submitted: [\"reviewing\", \"declined\"],\n reviewing: [\"interviewing\", \"approved\", \"declined\"],\n interviewing: [\"approved\", \"declined\"],\n approved: [\"forming\", \"declined\"],\n },\n },\n facets: { email: true, rank: \"manual\" },\n },\n deal: {\n label: \"Deal\",\n labelPlural: \"Deal flow\",\n workspace: \"portfolio\",\n nameField: \"name\",\n fields: {\n name: { type: \"string\", label: \"Company or deal\", required: true },\n chapter: { type: \"string\", label: \"Source chapter\", slot: \"s1\" },\n sector: { type: \"string\", label: \"Sector\", slot: \"s2\" },\n source: { type: \"string\", label: \"Source\", slot: \"s3\" },\n website: { type: \"url\", label: \"Website\" },\n amount: { type: \"number\", label: \"Target amount\", slot: \"n1\" },\n notes: { type: \"string\", label: \"Notes\" },\n },\n pipeline: {\n stages: [\n { id: \"sourced\", label: \"Sourced\" },\n { id: \"screening\", label: \"Screening\" },\n { id: \"diligence\", label: \"Diligence\" },\n { id: \"committee\", label: \"Committee\" },\n { id: \"offered\", label: \"Offered\" },\n { id: \"invested\", label: \"Invested\", terminal: true },\n { id: \"passed\", label: \"Passed\", terminal: true },\n ],\n transitions: {\n sourced: [\"screening\", \"passed\"],\n screening: [\"diligence\", \"committee\", \"passed\"],\n diligence: [\"committee\", \"offered\", \"passed\"],\n committee: [\"offered\", \"passed\"],\n offered: [\"invested\", \"passed\"],\n passed: [\"sourced\"],\n },\n },\n facets: { rank: \"manual\" },\n },\n },\n relations: {\n formation_result: {\n from: \"chapter_application\",\n to: \"chapter\",\n label: \"formed as\",\n reverseLabel: \"formation application\",\n },\n chapter_deal: {\n from: \"deal\",\n to: \"chapter\",\n label: \"sourced by\",\n reverseLabel: \"deal flow\",\n },\n },\n };\n if (base.types.company) {\n portfolio.relations!.deal_company = {\n from: \"deal\",\n to: \"company\",\n label: \"concerns\",\n reverseLabel: \"deals\",\n };\n }\n if (base.types.person) {\n portfolio.relations!.application_contact = {\n from: \"person\",\n to: \"chapter_application\",\n label: \"submitted\",\n reverseLabel: \"applicant\",\n };\n }\n return composeCrmConfigs(base, portfolio);\n}\n","// The CLI-consumable provisioning descriptor. It composes @odla-ai/crm's\n// integration (crm_* namespaces + crm_config seed + route probe) with the\n// chapter's own namespaces and a guarded `groups`-row seed, so a site's\n// odla.config.mjs lists ONE integration. The CLI reads it structurally\n// (matching OdlaIntegration) and merges schema/rules by namespace.\nimport { createCrmIntegration } from \"@odla-ai/crm\";\nimport { buildTierSeeds } from \"./tiers\";\nimport type { Chapter } from \"./types\";\n\n/** Options for {@link createChapterIntegration}. */\nexport interface ChapterIntegrationOptions {\n /** CRM route mount point. Default \"/api/crm\". */\n basePath?: string;\n /** Seed timestamp override for reproducible builds/tests. */\n now?: number;\n}\n\ninterface IntegrationSeed {\n id: string;\n ns: string;\n key: { attr: string; value: string };\n attrs: Record<string, unknown>;\n}\n\n/** Structural match for the CLI's `OdlaIntegration`. */\nexport interface ChapterIntegrationDescriptor {\n id: string;\n title: string;\n npm: string;\n schema: { entities: Record<string, unknown>; links: Record<string, unknown> };\n rules: Record<string, unknown>;\n seeds: IntegrationSeed[];\n probes: Array<{ path: string; expectedStatus: number }>;\n /** Runbooks that bear on THIS chapter's role, so tooling can point at the\n * right procedure without the operator knowing it exists. A chapter declaring\n * `network.targets` is a leader hub; one with no targets is a follower site\n * (and may declare `network.readers` for bounded CRM browsing). */\n runbooks: ChapterRunbookHints;\n}\n\n/** Which runbooks apply, and why. */\nexport interface ChapterRunbookHints {\n role: \"leader\" | \"follower\";\n /** Platform runbook slugs, most relevant first. */\n slugs: string[];\n /** One line a human or agent can act on. */\n guidance: string;\n}\n\n/**\n * Build the one CLI-consumable integration for a chapter/hub: the crm_*\n * namespaces + crm_config seed + route probe, merged with the chapter's own\n * namespaces and a guarded `groups`-row seed. Drop it in odla.config.mjs's\n * `integrations` array.\n */\nexport function createChapterIntegration(\n chapter: Chapter,\n options: ChapterIntegrationOptions = {},\n): ChapterIntegrationDescriptor {\n const basePath = options.basePath ?? \"/api/crm\";\n const now = options.now ?? Date.now();\n const emails = chapter.config.emails;\n\n const crmDesc = createCrmIntegration(chapter.crm, {\n basePath,\n now,\n ...(emails?.notificationEmail ? { notificationEmail: emails.notificationEmail } : {}),\n ...(emails?.replyTo ? { replyTo: emails.replyTo } : {}),\n ...(emails?.debugEmail ? { debugEmail: emails.debugEmail } : {}),\n });\n\n const seeds: IntegrationSeed[] = [...(crmDesc.seeds ?? [])];\n const group = chapter.groupSeed();\n if (group) {\n seeds.push({ id: \"group\", ns: \"groups\", key: { attr: \"id\", value: chapter.id }, attrs: { ...group, createdAt: now } });\n // One insert-only seed per declared tier, keyed by its own id so re-running\n // provisioning never duplicates a tier or overwrites a price an owner has\n // since changed in Studio.\n for (const tier of buildTierSeeds(chapter.id, chapter.config.tiers, now)) {\n seeds.push({\n id: `tier:${String(tier.id)}`,\n ns: \"tiers\",\n key: { attr: \"id\", value: String(tier.id) },\n attrs: tier,\n });\n }\n }\n\n // A leader declares where it pushes records. A follower declares no targets;\n // it may still declare readers for bounded record browsing.\n const isLeader = (chapter.config.network?.targets?.length ?? 0) > 0;\n const runbooks: ChapterRunbookHints = isLeader\n ? {\n role: \"leader\",\n slugs: [\"chapter-leader\", \"chapter-network\", \"crm\"],\n guidance:\n `${chapter.name} is a LEADER hub: it holds the CRM and shares records with its chapters. ` +\n `Read it with \\`odla-ai runbook get chapter-leader\\`.`,\n }\n : {\n role: \"follower\",\n slugs: [\"chapter-follower\", \"chapter-network\"],\n guidance:\n `${chapter.name} is a FOLLOWER site: it receives people and records from a leader hub. ` +\n `Read it with \\`odla-ai runbook get chapter-follower\\`.`,\n };\n\n return {\n id: \"chapter\",\n title: `Chapter: ${chapter.name}`,\n npm: \"@odla-ai/chapter\",\n schema: {\n entities: { ...crmDesc.schema.entities, ...chapter.schema.entities },\n links: { ...crmDesc.schema.links, ...chapter.schema.links },\n },\n rules: { ...crmDesc.rules, ...chapter.rules },\n seeds,\n probes: [\n ...(crmDesc.probes ?? []),\n // The snapshot route is deliberately private. A credential-free smoke\n // request must prove that the route is mounted and closed.\n { path: \"/api/network/snapshot\", expectedStatus: 401 },\n ...(chapter.network.readers.length > 0\n ? [{ path: \"/api/network/records\", expectedStatus: 401 }]\n : []),\n ...(chapter.network.readers.some((reader) => reader.sharedNotes.length > 0)\n ? [{\n path: \"/api/network/shared-notes\",\n expectedStatus: 401,\n }]\n : []),\n // Formation metadata is public only when the host explicitly enables\n // the bounded intake contract.\n ...(chapter.formation.enabled\n ? [{ path: \"/api/formation/config\", expectedStatus: 200 }]\n : []),\n ...(chapter.memberContent\n ? [\n { path: \"/api/member-content\", expectedStatus: 401 },\n { path: \"/api/admin/member-content\", expectedStatus: 401 },\n ]\n : []),\n ],\n runbooks,\n };\n}\n","// Membership tiers. A chapter offers one or more tiers, and a tier — not the\n// group — decides what a member pays. Keeping the price on the tier is what\n// makes a free tier expressible: `paymentsReady` used to gate the whole join\n// flow on the group holding a Stripe price, so a £0 membership was unjoinable.\n//\n// Everything here is pure so the join page, the checkout route and the seeder\n// agree about which tiers exist and which of them can actually be bought.\n\n/** One membership tier a chapter offers. `priceCents: 0` means free. */\nexport interface ChapterTier {\n /** Stable slug, referenced by `applications.tierId`. Never renumbered. */\n id: string;\n /** The group this tier belongs to. */\n groupId: string;\n /** Display name, e.g. \"Founding\". */\n name: string;\n /** Price in minor units. `0` is free and needs no Stripe price. */\n priceCents: number;\n /** Stripe price to subscribe. Required only when `priceCents > 0`. */\n stripePriceId?: string | null;\n /** Short description shown beside the tier on the join page. */\n blurb?: string;\n /** Ascending display order; ties fall back to `id` for a stable sort. */\n sortOrder: number;\n /** An inactive tier is retained for existing members but never offered. */\n active: boolean;\n}\n\n/**\n * A tier as declared in `defineChapter`, before it becomes a row.\n *\n * `groupId` is absent here because the chapter owns exactly one group at seed\n * time; the seeder fills it in.\n */\nexport interface ChapterTierConfig {\n id: string;\n name: string;\n priceCents: number;\n stripePriceId?: string;\n blurb?: string;\n /** Defaults to declaration order when omitted. */\n sortOrder?: number;\n /** Defaults to true; set false to retire a tier without deleting it. */\n active?: boolean;\n}\n\n/** Build the seed rows for a chapter's declared tiers. */\nexport function buildTierSeeds(\n groupId: string,\n configured: readonly ChapterTierConfig[] = [],\n now = 0,\n): Array<Record<string, unknown>> {\n return configured.map((tier, index) => ({\n id: tier.id,\n groupId,\n name: tier.name,\n priceCents: tier.priceCents,\n ...(tier.stripePriceId ? { stripePriceId: tier.stripePriceId } : {}),\n ...(tier.blurb ? { blurb: tier.blurb } : {}),\n sortOrder: tier.sortOrder ?? index,\n active: tier.active !== false,\n createdAt: now,\n }));\n}\n\n/** The `groups`-row fields tier payability depends on. */\nexport interface TierGroup {\n id?: string;\n stripePublishableKey?: string | null;\n /** Legacy single price, used only to synthesize an implicit tier. */\n stripePriceId?: string | null;\n standardPriceCents?: number;\n foundingDiscountCents?: number;\n}\n\n/**\n * Whether this tier costs nothing. A free tier never touches Stripe.\n *\n * Free means both no price AND no Stripe price to charge against. The second\n * half matters for chapters that predate tiers: a group can carry a real\n * `stripePriceId` while `standardPriceCents` is 0, because the cents field is\n * display copy and the amount actually lives in Stripe. Reading such a group as\n * free would silently stop charging an existing paying chapter.\n */\nexport function tierIsFree(\n tier: Pick<ChapterTier, \"priceCents\"> & { stripePriceId?: string | null },\n): boolean {\n return !(tier.priceCents > 0) && !tier.stripePriceId;\n}\n\n/**\n * Whether a tier can actually be joined right now.\n *\n * A free tier is always joinable — there is nothing to charge, so Stripe being\n * unconfigured is irrelevant to it. A paid tier needs the group's publishable\n * key, its own Stripe price, and the vault secret; missing any of those drops\n * the tier rather than half-charging for it.\n */\nexport function tierPayable(\n tier: Pick<ChapterTier, \"priceCents\" | \"stripePriceId\">,\n group: TierGroup,\n hasSecretKey: boolean,\n): boolean {\n if (tierIsFree(tier)) return true;\n return Boolean(group.stripePublishableKey && tier.stripePriceId && hasSecretKey);\n}\n\n/** Sort by `sortOrder`, then `id`, so a page never reorders between reads. */\nfunction byOrder(a: ChapterTier, b: ChapterTier): number {\n return a.sortOrder - b.sortOrder || a.id.localeCompare(b.id);\n}\n\n/**\n * The tiers a chapter offers, given the stored rows.\n *\n * A chapter that predates tiers has no rows, and must keep working untouched:\n * one implicit `\"standard\"` tier is synthesized from the group's legacy\n * `standardPriceCents`/`stripePriceId` columns. That is why there is no\n * migration — an existing chapter reads exactly as it did before, and writing\n * its first real tier row takes over.\n */\nexport function resolveTiers(group: TierGroup, rows: readonly ChapterTier[] = []): ChapterTier[] {\n const stored = rows.filter((tier) => tier.active);\n if (stored.length) return [...stored].sort(byOrder);\n return [{\n id: \"standard\",\n groupId: String(group.id ?? \"\"),\n name: \"Membership\",\n priceCents: group.standardPriceCents ?? 0,\n ...(group.stripePriceId ? { stripePriceId: group.stripePriceId } : {}),\n sortOrder: 0,\n active: true,\n }];\n}\n\n/** The tiers to show on the join page: active, and joinable as configured. */\nexport function offerableTiers(\n tiers: readonly ChapterTier[],\n group: TierGroup,\n hasSecretKey: boolean,\n): ChapterTier[] {\n return tiers.filter((tier) => tier.active && tierPayable(tier, group, hasSecretKey));\n}\n\n/**\n * Resolve the tier an application chose.\n *\n * An absent `tierId` is the pre-tier case and selects the only offered tier\n * when exactly one exists; with several it is genuinely ambiguous and returns\n * `null`, because guessing would charge someone the wrong price.\n */\nexport function findTier(\n tiers: readonly ChapterTier[],\n tierId: string | null | undefined,\n): ChapterTier | null {\n if (!tierId) return tiers.length === 1 ? tiers[0]! : null;\n return tiers.find((tier) => tier.id === tierId) ?? null;\n}\n\n/** The public shape of a tier on the join config. Never exposes Stripe ids. */\nexport interface JoinConfigTier {\n id: string;\n name: string;\n priceCents: number;\n blurb: string;\n free: boolean;\n}\n\n/** Project tiers for the public join config, dropping provider identifiers. */\nexport function joinConfigTiers(tiers: readonly ChapterTier[]): JoinConfigTier[] {\n return tiers.map((tier) => ({\n id: tier.id,\n name: tier.name,\n priceCents: tier.priceCents,\n blurb: tier.blurb ?? \"\",\n free: tierIsFree(tier),\n }));\n}\n","import type { MemberPageAudience, MemberPageUpsellOffer } from \"./member-content\";\n\nexport const ID = /^[a-z][a-z0-9-]{0,79}$/;\nexport const SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nexport const ROOT_KEYS = new Set([\"schemaVersion\", \"revision\", \"generatedAt\", \"source\", \"target\", \"pages\", \"upsellOverrides\"]);\nexport const SOURCE_KEYS = new Set([\"type\", \"appId\"]);\nexport const TARGET_KEYS = new Set([\"chapterId\", \"environment\"]);\nexport const PAGE_KEYS = new Set([\"id\", \"slug\", \"title\", \"summary\", \"navigation\", \"audience\", \"teaserMarkdown\", \"bodyMarkdown\", \"upsell\"]);\nexport const NAV_KEYS = new Set([\"section\", \"order\", \"parentId\"]);\nexport const AUDIENCE_KEYS = new Set([\"kind\", \"tierIds\"]);\nexport const UPSELL_KEYS = new Set([\"owner\", \"offer\"]);\nexport const OFFER_KEYS = new Set([\"tierId\", \"label\", \"bodyMarkdown\", \"ctaLabel\"]);\nexport const OVERRIDE_KEYS = new Set([\"pageId\", \"offer\"]);\nexport const MAX_PAGES = 100;\nexport const MAX_MARKDOWN = 65_536;\nexport const MAX_TEXT = 240;\n\nexport const record = (value: unknown): Record<string, unknown> | null =>\n value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null;\n\nexport function unknownKeys(value: Record<string, unknown>, allowed: ReadonlySet<string>, path: string, errors: string[]): void {\n for (const key of Object.keys(value)) if (!allowed.has(key)) errors.push(`${path}.${key} is not supported`);\n}\n\nexport function textValue(value: unknown, path: string, errors: string[], max = MAX_TEXT, required = false): string | undefined {\n if (value === undefined) {\n if (required) errors.push(`${path} is required`);\n return undefined;\n }\n if (typeof value !== \"string\") {\n errors.push(`${path} must be a string`);\n return undefined;\n }\n const valueText = value.trim();\n if (required && !valueText) errors.push(`${path} is required`);\n if (valueText.length > max) errors.push(`${path} must be at most ${max.toLocaleString(\"en-US\")} characters`);\n return valueText;\n}\n\nexport function offerValue(\n value: unknown,\n path: string,\n errors: string[],\n tiers: ReadonlySet<string>,\n audience?: MemberPageAudience,\n): MemberPageUpsellOffer | undefined {\n const raw = record(value);\n if (!raw) {\n errors.push(`${path} must be an object`);\n return undefined;\n }\n unknownKeys(raw, OFFER_KEYS, path, errors);\n const tierId = textValue(raw.tierId, `${path}.tierId`, errors, 80, true) ?? \"\";\n if (tierId && !ID.test(tierId)) errors.push(`${path}.tierId must be a lowercase kebab-case id`);\n if (tiers.size && !tiers.has(tierId)) errors.push(`${path}.tierId must reference a declared tier`);\n if (audience?.kind === \"tiers\" && tierId && !audience.tierIds.includes(tierId)) {\n errors.push(`${path}.tierId must grant access to this page`);\n }\n const label = textValue(raw.label, `${path}.label`, errors);\n const bodyMarkdown = textValue(raw.bodyMarkdown, `${path}.bodyMarkdown`, errors, MAX_MARKDOWN);\n const ctaLabel = textValue(raw.ctaLabel, `${path}.ctaLabel`, errors);\n return {\n tierId,\n ...(label ? { label } : {}),\n ...(bodyMarkdown ? { bodyMarkdown } : {}),\n ...(ctaLabel ? { ctaLabel } : {}),\n };\n}\n","import {\n MEMBER_CONTENT_SCHEMA_VERSION,\n type MemberContentDocument,\n type MemberContentPage,\n type MemberContentSource,\n type MemberContentTarget,\n type MemberContentValidationOptions,\n type MemberContentValidationResult,\n type MemberPageAudience,\n type MemberPageNavigation,\n type MemberPageUpsell,\n type MemberPageUpsellOverride,\n} from \"./member-content\";\nimport {\n AUDIENCE_KEYS,\n ID,\n MAX_MARKDOWN,\n MAX_PAGES,\n MAX_TEXT,\n NAV_KEYS,\n OVERRIDE_KEYS,\n PAGE_KEYS,\n ROOT_KEYS,\n SLUG,\n SOURCE_KEYS,\n TARGET_KEYS,\n UPSELL_KEYS,\n offerValue,\n record,\n textValue,\n unknownKeys,\n} from \"./member-content-validation-helpers\";\n\n/** Validate one complete parent or chapter authoring layer with actionable paths. */\nexport function validateMemberContentDocument(\n input: unknown,\n options: MemberContentValidationOptions = {},\n): MemberContentValidationResult {\n const errors: string[] = [];\n const root = record(input);\n if (!root) return { ok: false, errors: [\"document must be an object\"] };\n unknownKeys(root, ROOT_KEYS, \"document\", errors);\n if (root.schemaVersion !== MEMBER_CONTENT_SCHEMA_VERSION) errors.push(\"document.schemaVersion must be 1\");\n if (!Number.isInteger(root.revision) || Number(root.revision) < 1) errors.push(\"document.revision must be a positive integer\");\n if (!Number.isInteger(root.generatedAt) || Number(root.generatedAt) < 0) errors.push(\"document.generatedAt must be a non-negative integer timestamp\");\n\n const sourceRaw = record(root.source);\n let source: MemberContentSource = { type: \"chapter\", appId: \"invalid\" };\n if (!sourceRaw) errors.push(\"document.source must be an object\");\n else {\n unknownKeys(sourceRaw, SOURCE_KEYS, \"document.source\", errors);\n const type = sourceRaw.type;\n const appId = textValue(sourceRaw.appId, \"document.source.appId\", errors, 63, true) ?? \"\";\n if (type !== \"parent\" && type !== \"chapter\") errors.push(\"document.source.type must be parent or chapter\");\n if (appId && !ID.test(appId)) errors.push(\"document.source.appId must be a lowercase app slug\");\n if (options.sourceType && type !== options.sourceType) errors.push(`document.source.type must be ${options.sourceType}`);\n if (options.sourceAppId && appId !== options.sourceAppId) errors.push(`document.source.appId must be ${options.sourceAppId}`);\n if (type === \"parent\" || type === \"chapter\") source = { type, appId };\n }\n\n let target: MemberContentTarget | undefined;\n if (root.target !== undefined) {\n const targetRaw = record(root.target);\n if (!targetRaw) errors.push(\"document.target must be an object\");\n else {\n unknownKeys(targetRaw, TARGET_KEYS, \"document.target\", errors);\n const chapterId = textValue(targetRaw.chapterId, \"document.target.chapterId\", errors, 63, true) ?? \"\";\n const environment = textValue(targetRaw.environment, \"document.target.environment\", errors, 80, true) ?? \"\";\n target = { chapterId, environment };\n }\n }\n if (source.type === \"parent\" && !target) errors.push(\"document.target is required for parent content\");\n if (source.type === \"chapter\" && target) errors.push(\"document.target is not supported for chapter content\");\n\n if (!Array.isArray(root.pages)) errors.push(\"document.pages must be an array\");\n const rawPages = Array.isArray(root.pages) ? root.pages : [];\n if (rawPages.length > MAX_PAGES) errors.push(`document.pages supports at most ${MAX_PAGES} entries`);\n const tierIds = new Set((options.tiers ?? []).map((tier) => tier.id));\n const knownParentIds = new Set((options.parentPages ?? []).map((page) => page.id));\n const ids = new Set<string>();\n const slugs = new Set<string>();\n const pages: MemberContentPage[] = [];\n for (const [index, value] of rawPages.slice(0, MAX_PAGES).entries()) {\n const path = `document.pages[${index}]`;\n const raw = record(value);\n if (!raw) {\n errors.push(`${path} must be an object`);\n continue;\n }\n unknownKeys(raw, PAGE_KEYS, path, errors);\n const id = textValue(raw.id, `${path}.id`, errors, 80, true) ?? \"\";\n const slug = textValue(raw.slug, `${path}.slug`, errors, 120, true) ?? \"\";\n const title = textValue(raw.title, `${path}.title`, errors, MAX_TEXT, true) ?? \"\";\n if (id && !ID.test(id)) errors.push(`${path}.id must be a lowercase kebab-case id`);\n if (slug && !SLUG.test(slug)) errors.push(`${path}.slug must be a lowercase URL slug`);\n if (ids.has(id) || knownParentIds.has(id)) errors.push(`${path}.id duplicates page \"${id}\"`);\n if (slugs.has(slug) || (options.parentPages ?? []).some((page) => page.slug === slug)) errors.push(`${path}.slug duplicates \"${slug}\"`);\n ids.add(id);\n slugs.add(slug);\n\n const navRaw = record(raw.navigation);\n let navigation: MemberPageNavigation = { section: \"General\", order: index };\n if (!navRaw) errors.push(`${path}.navigation must be an object`);\n else {\n unknownKeys(navRaw, NAV_KEYS, `${path}.navigation`, errors);\n const section = textValue(navRaw.section, `${path}.navigation.section`, errors, 120, true) ?? \"\";\n const order = navRaw.order;\n if (!Number.isInteger(order) || Number(order) < 0 || Number(order) > 1_000_000) {\n errors.push(`${path}.navigation.order must be an integer from 0 to 1,000,000`);\n }\n const parentId = textValue(navRaw.parentId, `${path}.navigation.parentId`, errors, 80);\n navigation = { section, order: Number.isInteger(order) ? Number(order) : index, ...(parentId ? { parentId } : {}) };\n }\n\n const audienceRaw = record(raw.audience);\n let audience: MemberPageAudience = { kind: \"all-members\" };\n if (!audienceRaw) errors.push(`${path}.audience must be an object`);\n else {\n unknownKeys(audienceRaw, AUDIENCE_KEYS, `${path}.audience`, errors);\n if (audienceRaw.kind === \"all-members\") {\n if (audienceRaw.tierIds !== undefined) errors.push(`${path}.audience.tierIds is not supported for all-members`);\n } else if (audienceRaw.kind === \"tiers\") {\n if (!Array.isArray(audienceRaw.tierIds) || audienceRaw.tierIds.length === 0) {\n errors.push(`${path}.audience.tierIds must be a non-empty array`);\n }\n const values = Array.isArray(audienceRaw.tierIds) ? audienceRaw.tierIds : [];\n const normalized: string[] = [];\n for (const [tierIndex, value] of values.entries()) {\n const tier = textValue(value, `${path}.audience.tierIds[${tierIndex}]`, errors, 80, true) ?? \"\";\n if (normalized.includes(tier)) errors.push(`${path}.audience.tierIds duplicates \"${tier}\"`);\n if (tierIds.size && !tierIds.has(tier)) errors.push(`${path}.audience.tierIds references undeclared tier \"${tier}\"`);\n normalized.push(tier);\n }\n audience = { kind: \"tiers\", tierIds: normalized };\n } else errors.push(`${path}.audience.kind must be all-members or tiers`);\n }\n\n const summary = textValue(raw.summary, `${path}.summary`, errors, 2_000);\n const teaserMarkdown = textValue(raw.teaserMarkdown, `${path}.teaserMarkdown`, errors, MAX_MARKDOWN);\n const bodyMarkdown = textValue(raw.bodyMarkdown, `${path}.bodyMarkdown`, errors, MAX_MARKDOWN, true) ?? \"\";\n let upsell: MemberPageUpsell | undefined;\n if (raw.upsell !== undefined) {\n const upsellRaw = record(raw.upsell);\n if (!upsellRaw) errors.push(`${path}.upsell must be an object`);\n else {\n unknownKeys(upsellRaw, UPSELL_KEYS, `${path}.upsell`, errors);\n const owner = upsellRaw.owner;\n if (owner !== \"parent\" && owner !== \"chapter\") errors.push(`${path}.upsell.owner must be parent or chapter`);\n if (source.type === \"chapter\" && owner === \"parent\") errors.push(`${path}.upsell.owner cannot be parent on a chapter page`);\n if (source.type === \"parent\" && owner === \"parent\" && upsellRaw.offer === undefined) errors.push(`${path}.upsell.offer is required when the parent owns the offer`);\n if (source.type === \"parent\" && owner === \"chapter\" && upsellRaw.offer !== undefined) errors.push(`${path}.upsell.offer must be set by the chapter after delegation`);\n const offer = upsellRaw.offer === undefined ? undefined : offerValue(upsellRaw.offer, `${path}.upsell.offer`, errors, tierIds, audience);\n if (owner === \"parent\") upsell = { owner, offer: offer ?? { tierId: \"\" } };\n else if (owner === \"chapter\") upsell = { owner, ...(offer ? { offer } : {}) };\n }\n }\n pages.push({ id, slug, title, ...(summary ? { summary } : {}), navigation, audience, ...(teaserMarkdown ? { teaserMarkdown } : {}), bodyMarkdown, ...(upsell ? { upsell } : {}) });\n }\n\n const allIds = new Set([...knownParentIds, ...ids]);\n for (const [index, page] of pages.entries()) {\n const parentId = page.navigation.parentId;\n if (parentId && !allIds.has(parentId)) errors.push(`document.pages[${index}].navigation.parentId references unknown page \"${parentId}\"`);\n if (parentId === page.id) errors.push(`document.pages[${index}].navigation.parentId cannot reference itself`);\n }\n for (const page of pages) {\n const seen = new Set([page.id]);\n let parentId = page.navigation.parentId;\n while (parentId) {\n if (seen.has(parentId)) {\n errors.push(`document.pages contains a navigation cycle at \"${page.id}\"`);\n break;\n }\n seen.add(parentId);\n parentId = pages.find((candidate) => candidate.id === parentId)?.navigation.parentId;\n }\n }\n\n let upsellOverrides: MemberPageUpsellOverride[] | undefined;\n if (root.upsellOverrides !== undefined) {\n if (source.type !== \"chapter\") errors.push(\"document.upsellOverrides is supported only for chapter content\");\n if (!Array.isArray(root.upsellOverrides)) errors.push(\"document.upsellOverrides must be an array\");\n const values = Array.isArray(root.upsellOverrides) ? root.upsellOverrides : [];\n const seen = new Set<string>();\n upsellOverrides = [];\n for (const [index, value] of values.entries()) {\n const path = `document.upsellOverrides[${index}]`;\n const raw = record(value);\n if (!raw) {\n errors.push(`${path} must be an object`);\n continue;\n }\n unknownKeys(raw, OVERRIDE_KEYS, path, errors);\n const pageId = textValue(raw.pageId, `${path}.pageId`, errors, 80, true) ?? \"\";\n if (seen.has(pageId)) errors.push(`${path}.pageId duplicates \"${pageId}\"`);\n seen.add(pageId);\n const parentPage = (options.parentPages ?? []).find((page) => page.id === pageId);\n if (!parentPage) errors.push(`${path}.pageId must reference a parent page`);\n else if (parentPage.upsell?.owner !== \"chapter\") errors.push(`${path}.pageId does not delegate upsell authority to the chapter`);\n const offer = offerValue(raw.offer, `${path}.offer`, errors, tierIds, parentPage?.audience);\n if (offer) upsellOverrides.push({ pageId, offer });\n }\n }\n if (errors.length) return { ok: false, errors };\n return { ok: true, value: {\n schemaVersion: MEMBER_CONTENT_SCHEMA_VERSION,\n revision: Number(root.revision),\n generatedAt: Number(root.generatedAt),\n source,\n ...(target ? { target } : {}),\n pages,\n ...(upsellOverrides ? { upsellOverrides } : {}),\n } };\n}\n\n/** Validate or fail closed with every actionable document error. */\nexport function memberContentDocument(input: unknown, options: MemberContentValidationOptions = {}): MemberContentDocument {\n const result = validateMemberContentDocument(input, options);\n if (!result.ok) throw new TypeError(`Invalid member content document: ${result.errors.join(\"; \")}`);\n return result.value;\n}\n","/** Versioned contract for authenticated member content. */\nexport const MEMBER_CONTENT_SCHEMA_VERSION = 1 as const;\n/** Authenticated member projection endpoint. */\nexport const MEMBER_CONTENT_PATH = \"/api/member-content\" as const;\n/** Dedicated signed Parent → Chapter content-delivery endpoint. */\nexport const MEMBER_CONTENT_CONTROL_PATH = \"/api/member-content-control\" as const;\n\n/** Authority that authored one independently stored member-content layer. */\nexport type MemberContentSourceType = \"parent\" | \"chapter\";\n/** Stable author identity attached to every member-content document and page. */\nexport interface MemberContentSource { type: MemberContentSourceType; appId: string }\n/** Chapter deployment that a parent member-content revision is intended for. */\nexport interface MemberContentTarget { chapterId: string; environment: string }\n\n/** Navigation is data, so agents do not have to coordinate route code. */\nexport interface MemberPageNavigation {\n section: string;\n order: number;\n parentId?: string;\n}\n\n/** Explicit sets avoid unsafe assumptions that commercial tiers form a ladder. */\nexport type MemberPageAudience =\n | { kind: \"all-members\" }\n | { kind: \"tiers\"; tierIds: readonly string[] };\n\n/** Authored offer copy. Price and provider identity deliberately do not live here. */\nexport interface MemberPageUpsellOffer {\n tierId: string;\n label?: string;\n bodyMarkdown?: string;\n ctaLabel?: string;\n}\n\n/** Parent offer authority is explicit; a Chapter can edit only a delegated offer. */\nexport type MemberPageUpsell =\n | { owner: \"parent\"; offer: MemberPageUpsellOffer }\n | { owner: \"chapter\"; offer?: MemberPageUpsellOffer };\n\n/** Authored member page whose body is disclosed only after server-side projection. */\nexport interface MemberContentPage {\n id: string;\n slug: string;\n title: string;\n summary?: string;\n navigation: MemberPageNavigation;\n audience: MemberPageAudience;\n /** Safe Markdown shown while the body is withheld. */\n teaserMarkdown?: string;\n /** Never serialized to a viewer whose audience does not match. */\n bodyMarkdown: string;\n upsell?: MemberPageUpsell;\n}\n\n/** Chapter-owned offer attached to a Parent page that delegated offer authority. */\nexport interface MemberPageUpsellOverride { pageId: string; offer: MemberPageUpsellOffer }\n\n/** One complete source layer. Parent and Chapter layers are stored independently. */\nexport interface MemberContentDocument {\n schemaVersion: typeof MEMBER_CONTENT_SCHEMA_VERSION;\n revision: number;\n generatedAt: number;\n source: MemberContentSource;\n target?: MemberContentTarget;\n pages: readonly MemberContentPage[];\n upsellOverrides?: readonly MemberPageUpsellOverride[];\n}\n\n/** Provider-neutral tier facts used to validate access and resolve safe offers. */\nexport interface MemberContentTierAuthority {\n id: string;\n name?: string;\n priceCents?: number;\n active?: boolean;\n}\n\n/** Local authority supplied while validating a member-content document. */\nexport interface MemberContentValidationOptions {\n sourceType?: MemberContentSourceType;\n sourceAppId?: string;\n tiers?: readonly MemberContentTierAuthority[];\n parentPages?: readonly MemberContentPage[];\n}\n\n/** Validated document or an actionable collection of contract errors. */\nexport type MemberContentValidationResult =\n | { ok: true; value: MemberContentDocument }\n | { ok: false; errors: readonly string[] };\n\n/** Composed member page retaining the identity of its authoring layer. */\nexport interface EffectiveMemberContentPage extends MemberContentPage { source: MemberContentSource }\n/** Deterministically ordered parent and chapter layers with their source revisions. */\nexport interface EffectiveMemberContent {\n pages: readonly EffectiveMemberContentPage[];\n parentRevision: number | null;\n chapterRevision: number | null;\n}\n/** Server-authoritative identity facts used for member-content disclosure. */\nexport interface MemberContentViewer { tierId: string | null; admin: boolean }\n/** Authored upsell joined to active chapter tier name and price authority. */\nexport interface ResolvedMemberPageUpsell extends MemberPageUpsellOffer { tierName: string; priceCents: number }\n\n/** Viewer-safe page result; locked projections never carry bodyMarkdown. */\nexport interface MemberContentPageProjection {\n id: string;\n slug: string;\n title: string;\n summary?: string;\n navigation: MemberPageNavigation;\n audience: MemberPageAudience;\n source: MemberContentSource;\n access: \"allowed\" | \"locked\";\n teaserMarkdown?: string;\n bodyMarkdown?: string;\n upsell?: ResolvedMemberPageUpsell;\n}\n\n/** Complete viewer-safe member navigation and revision projection. */\nexport interface MemberContentProjection {\n pages: readonly MemberContentPageProjection[];\n viewer: { tierId: string | null; admin: boolean };\n revisions: { parent: number | null; chapter: number | null };\n}\n\n/** Canonical parent document and digest transmitted over the signed control edge. */\nexport interface MemberContentEnvelope { digest: string; document: MemberContentDocument }\n/** Durable Chapter acknowledgement for an accepted or idempotently replayed revision. */\nexport interface MemberContentReceipt {\n ok: true;\n target: MemberContentTarget;\n revision: number;\n digest: string;\n status: \"accepted\" | \"replayed\";\n acknowledgedAt: number;\n}\n\n/** Stable rejection reasons returned by the signed member-content control endpoint. */\nexport type MemberContentRejection =\n | \"invalid_document\"\n | \"invalid_digest\"\n | \"wrong_source\"\n | \"wrong_target\"\n | \"wrong_environment\"\n | \"stale_revision\"\n | \"conflicting_revision\"\n | \"materialization_failed\";\n\nexport { memberContentDocument, validateMemberContentDocument } from \"./member-content-validation\";\n\nconst pageOrder = (a: EffectiveMemberContentPage, b: EffectiveMemberContentPage): number =>\n a.navigation.section.localeCompare(b.navigation.section)\n || a.navigation.order - b.navigation.order\n || a.title.localeCompare(b.title)\n || a.id.localeCompare(b.id);\n\n/** Compose immutable Parent content with independently stored Chapter content. */\nexport function composeMemberContent(\n parent: MemberContentDocument | null | undefined,\n chapter: MemberContentDocument | null | undefined,\n): EffectiveMemberContent {\n const pages: EffectiveMemberContentPage[] = [];\n const parentPages = new Map<string, EffectiveMemberContentPage>();\n for (const page of parent?.pages ?? []) {\n const effective = { ...page, source: parent!.source };\n parentPages.set(page.id, effective);\n pages.push(effective);\n }\n for (const override of chapter?.upsellOverrides ?? []) {\n const page = parentPages.get(override.pageId);\n if (page?.upsell?.owner === \"chapter\") page.upsell = { owner: \"chapter\", offer: override.offer };\n }\n for (const page of chapter?.pages ?? []) {\n if (parentPages.has(page.id) || pages.some((candidate) => candidate.slug === page.slug)) {\n throw new TypeError(`Chapter member page \"${page.id}\" conflicts with parent content`);\n }\n pages.push({ ...page, source: chapter!.source });\n }\n return {\n pages: pages.sort(pageOrder),\n parentRevision: parent?.revision ?? null,\n chapterRevision: chapter?.revision ?? null,\n };\n}\n\nconst allowed = (page: MemberContentPage, viewer: MemberContentViewer): boolean =>\n viewer.admin\n || page.audience.kind === \"all-members\"\n || (viewer.tierId !== null && page.audience.tierIds.includes(viewer.tierId));\n\n/** Restricted bodies are omitted and authored offers are joined to live tier authority. */\nexport function projectMemberContent(\n content: EffectiveMemberContent,\n viewer: MemberContentViewer,\n tiers: readonly MemberContentTierAuthority[],\n): MemberContentProjection {\n const authority = new Map(tiers.filter((tier) => tier.active !== false).map((tier) => [tier.id, tier]));\n return {\n viewer: { ...viewer },\n revisions: { parent: content.parentRevision, chapter: content.chapterRevision },\n pages: content.pages.map((page) => {\n const canRead = allowed(page, viewer);\n const offer = !canRead ? page.upsell?.offer : undefined;\n const tier = offer ? authority.get(offer.tierId) : undefined;\n const upsell = offer && tier && typeof tier.name === \"string\" && typeof tier.priceCents === \"number\"\n ? { ...offer, tierName: tier.name, priceCents: tier.priceCents }\n : undefined;\n return {\n id: page.id,\n slug: page.slug,\n title: page.title,\n ...(page.summary ? { summary: page.summary } : {}),\n navigation: page.navigation,\n audience: page.audience,\n source: page.source,\n access: canRead ? \"allowed\" as const : \"locked\" as const,\n ...(page.teaserMarkdown ? { teaserMarkdown: page.teaserMarkdown } : {}),\n ...(canRead ? { bodyMarkdown: page.bodyMarkdown } : {}),\n ...(upsell ? { upsell } : {}),\n };\n }),\n };\n}\n","const encoder = new TextEncoder();\n\nfunction canonicalValue(value: unknown): string {\n if (value === null || typeof value === \"boolean\" || typeof value === \"number\" || typeof value === \"string\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) return `[${value.map(canonicalValue).join(\",\")}]`;\n if (typeof value !== \"object\") throw new TypeError(\"member content contains an unsupported value\");\n const record = value as Record<string, unknown>;\n const entries = Object.keys(record).sort().flatMap((key) => {\n const item = record[key];\n return item === undefined ? [] : [`${JSON.stringify(key)}:${canonicalValue(item)}`];\n });\n return `{${entries.join(\",\")}}`;\n}\n\n/** Serialize JSON-like member content with recursively sorted object keys. */\nexport function canonicalMemberContent(value: unknown): string {\n return canonicalValue(value);\n}\n\n/** Compute the canonical SHA-256 digest for one Parent content revision. */\nexport async function memberContentDigest(document: unknown): Promise<string> {\n const digest = await crypto.subtle.digest(\"SHA-256\", encoder.encode(canonicalMemberContent(document)));\n return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\n/** Pair one content document with the exact digest the follower acknowledges. */\nexport async function createMemberContentEnvelope(document: import(\"./member-content\").MemberContentDocument) {\n return { document, digest: await memberContentDigest(document) };\n}\n","// The chapter email pipeline: exactly-once delivery, a non-production fail-safe,\n// and template rendering. Every property here is easy to get wrong and expensive\n// to get wrong, so the correctness-critical decisions — the dedupe check (E1),\n// the dev-redirect / log-only fail-safe (E2), and template rendering (E4) — are\n// PURE and fully tested in this module. The worker supplies the transport +\n// odla-db and performs the actual send + emailLog write around these decisions.\n//\n// Chapter's operational templates ({ subject, text, enabled? }) are\n// transactional lifecycle mail by construction — a site owner edits the copy in\n// Settings but cannot reclassify one as marketing. Consent-gated marketing blasts\n// go through @odla-ai/crm, which owns the transactional-vs-marketing template\n// class as code (E3), so relabeling copy can never bypass the consent gate.\n\n/** One owner-editable template row on the group. `enabled` absent = enabled. */\nexport interface EmailTemplateRow {\n subject: string;\n text: string;\n enabled?: boolean;\n}\n\n/** The `groups`-row fields the email pipeline reads. */\nexport interface EmailGroup {\n id: string;\n name: string;\n replyTo: string;\n /** Non-prod debug inbox: all mail redirects here outside prod (E2). */\n debugEmail?: string;\n refundPolicyText?: string;\n commitmentText?: string;\n normsText?: string;\n emailTemplates: Record<string, EmailTemplateRow>;\n}\n\n/** `{{placeholder}}` substitution; unknown placeholders render empty. */\nexport function render(template: string, vars: Record<string, string>): string {\n return template.replace(/\\{\\{(\\w+)\\}\\}/g, (_, key: string) => vars[key] ?? \"\");\n}\n\n/** Group-level vars every template receives, under the caller's vars. */\nfunction groupVars(group: EmailGroup, vars: Record<string, string>): Record<string, string> {\n return {\n ...vars,\n refundPolicyText: group.refundPolicyText ?? \"\",\n commitmentText: group.commitmentText ?? \"\",\n normsText: group.normsText ?? \"\",\n };\n}\n\n/**\n * Re-render a template's body for history/preview (E4): the CRM comms history\n * reads back emails whose body predates `emailLog.body` by rendering the current\n * template with the recipient's vars. Same substitution + group vars as the send\n * path. `null` for an unknown template. Reflects the copy as it reads today, not\n * necessarily the exact bytes originally sent (only `emailLog.body` is byte-exact).\n */\nexport function renderTemplateBody(group: EmailGroup, template: string, vars: Record<string, string>): string | null {\n const tpl = group.emailTemplates?.[template];\n if (!tpl) return null;\n return render(tpl.text, groupVars(group, vars));\n}\n\n/**\n * E1 (exactly-once): given the prior `emailLog` rows for a `dedupeKey`, has the\n * mail already been delivered? A prior row with **no error** means yes — the\n * caller short-circuits the resend. Failure rows (which carry an `error` and are\n * written without the dedupe mutationId) do not count, so a retry after a failure\n * can still succeed.\n */\nexport function isAlreadySent(priorRows: ReadonlyArray<{ error?: unknown }>): boolean {\n return priorRows.some((row) => !row.error);\n}\n\n/** The pure delivery decision produced by {@link planDelivery}. */\nexport type DeliveryDecision =\n | { deliver: false; reason: \"template-missing\" | \"disabled\" }\n | {\n deliver: true;\n /** Which transport to use — `log-only` records the send but delivers nothing. */\n transport: \"cloudflare\" | \"log-only\";\n to: string;\n subject: string;\n text: string;\n /** True when redirected to the non-prod debug inbox. */\n redirected: boolean;\n };\n\n/**\n * The pure delivery decision (E2 fail-safe + E3 enabled). Given the env, group,\n * template, recipient, and whether a real Cloudflare transport is wired:\n * - missing template → not delivered (`template-missing`);\n * - disabled template and not forced → not delivered (`disabled`);\n * - **non-prod with a debug inbox** → REDIRECT to it, `\"[dev] \"` subject prefix,\n * a dev-redirect note in the body, so test applicants never receive real mail;\n * - **non-prod with NO debug inbox** → force `log-only` (deliver nothing) — the\n * fail-safe that protects every site's test data;\n * - prod → deliver via the real transport (`cloudflare` if wired, else `log-only`).\n */\nexport function planDelivery(input: {\n envName: string;\n group: EmailGroup;\n template: string;\n to: string;\n vars: Record<string, string>;\n /** Whether a Cloudflare Email Service transport (binding + verified from) is wired. */\n cloudflareReady: boolean;\n /** The admin test route may send a disabled template. */\n force?: boolean;\n}): DeliveryDecision {\n const tpl = input.group.emailTemplates?.[input.template];\n if (!tpl) return { deliver: false, reason: \"template-missing\" };\n if (tpl.enabled === false && !input.force) return { deliver: false, reason: \"disabled\" };\n\n const vars = groupVars(input.group, input.vars);\n const isProd = input.envName === \"prod\";\n const redirect = !isProd && !!input.group.debugEmail;\n const transport: \"cloudflare\" | \"log-only\" =\n !isProd && !redirect ? \"log-only\" : input.cloudflareReady ? \"cloudflare\" : \"log-only\";\n const to = redirect ? (input.group.debugEmail as string) : input.to;\n const subject = (redirect ? \"[dev] \" : \"\") + render(tpl.subject, vars);\n const text = redirect\n ? `(dev redirect; original recipient: ${input.to})\\n\\n` + render(tpl.text, vars)\n : render(tpl.text, vars);\n return { deliver: true, transport, to, subject, text, redirected: redirect };\n}\n","// sendTemplated — the operational-email orchestration that wires the pure email\n// decisions (./email: isAlreadySent E1, planDelivery E2/E3) to odla-db + a\n// transport. Structural (takes a ChapterDb + a sender), so it's FakeDb-testable\n// like submitApplication/projectSharedRecord. The worker's lifecycle routes call\n// it to send the prep / payment-confirmation / admin-alert mail.\n//\n// Exactly-once is enforced twice: a prior successful emailLog row short-circuits\n// the resend (query + isAlreadySent), AND the success row is written under the\n// `email:${dedupeKey}` mutationId so a racing double-send dedupes at the db layer.\n// Failure rows omit the mutationId, so a retry after a transient failure can send.\nimport { isAlreadySent, planDelivery } from \"./email\";\nimport type { EmailGroup } from \"./email\";\nimport type { ChapterDb } from \"./types\";\n\n/** The canonical lifecycle email templates chapter fires, in send-order. Owner-\n * editable copy lives on the group row; this is the fixed set the admin email\n * editor + test route iterate. */\nexport const EMAIL_TEMPLATE_NAMES = [\"adminNotification\", \"paymentConfirmation\", \"prepEmail\", \"onboardingInvite\"] as const;\n\n/** One of {@link EMAIL_TEMPLATE_NAMES}. */\nexport type EmailTemplateName = (typeof EMAIL_TEMPLATE_NAMES)[number];\n\n/** The mail transport (the worker's Cloudflare SEND_EMAIL binding). */\nexport interface MailSender {\n send(payload: { from: string; to: string[]; subject: string; text?: string; replyTo?: string }): Promise<{ messageId: string }>;\n}\n\n/** Deps for {@link sendTemplated} — the db, the env name (drives the fail-safe),\n * the transport + from (absent ⇒ log-only), and injected clock/id. */\nexport interface NotifyDeps {\n db: ChapterDb;\n envName: string;\n sender?: MailSender;\n from?: string;\n now: () => number;\n newId: () => string;\n}\n\n/** One templated send. `dedupeKey` is the exactly-once key. */\nexport interface NotifyInput {\n group: EmailGroup;\n template: string;\n to: string;\n vars: Record<string, string>;\n dedupeKey: string;\n applicationId?: string;\n /** The admin test route may send a disabled template. */\n force?: boolean;\n}\n\n/** The outcome. `sent:true` includes the already-sent short-circuit. */\nexport interface NotifyResult {\n sent: boolean;\n reason?: string;\n}\n\n/**\n * Send a templated lifecycle email exactly once. Short-circuits on a prior\n * successful send; otherwise plans delivery (dev fail-safe applies), sends via the\n * transport when one is wired and the plan calls for it, and records an emailLog\n * row either way (success keyed for exactly-once, failure unkeyed for retry).\n */\nexport async function sendTemplated(deps: NotifyDeps, input: NotifyInput): Promise<NotifyResult> {\n const { emailLog } = await deps.db.query({ emailLog: { $: { where: { dedupeKey: input.dedupeKey } } } });\n const prior = (Array.isArray(emailLog) ? emailLog : []) as Array<{ error?: unknown }>;\n if (isAlreadySent(prior)) return { sent: true, reason: \"already-sent\" };\n\n const cloudflareReady = Boolean(deps.sender && deps.from);\n const decision = planDelivery({\n envName: deps.envName,\n group: input.group,\n template: input.template,\n to: input.to,\n vars: input.vars,\n cloudflareReady,\n force: input.force,\n });\n if (!decision.deliver) return { sent: false, reason: decision.reason };\n\n let error: string | undefined;\n let messageId: string | undefined;\n if (decision.transport === \"cloudflare\" && deps.sender && deps.from) {\n try {\n const res = await deps.sender.send({\n from: deps.from,\n to: [decision.to],\n subject: decision.subject,\n text: decision.text,\n replyTo: input.group.replyTo,\n });\n messageId = res.messageId;\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n }\n }\n\n const id = deps.newId();\n const row: Record<string, unknown> = {\n id,\n groupId: input.group.id,\n to: decision.to,\n template: input.template,\n subject: decision.subject,\n body: decision.text,\n transport: decision.transport,\n redirected: decision.redirected,\n dedupeKey: input.dedupeKey,\n sentAt: deps.now(),\n ...(input.applicationId ? { applicationId: input.applicationId } : {}),\n ...(messageId ? { messageId } : {}),\n ...(error ? { error } : {}),\n };\n await deps.db.transact([{ t: \"update\", ns: \"emailLog\", id, attrs: row }], error ? undefined : { mutationId: `email:${input.dedupeKey}` });\n return error ? { sent: false, reason: error } : { sent: true };\n}\n\n/** Project a `groups` row into the {@link EmailGroup} the email pipeline reads. */\nexport function emailGroupFrom(row: Record<string, unknown>): EmailGroup {\n const str = (v: unknown): string | undefined => (typeof v === \"string\" ? v : undefined);\n const templates = row.emailTemplates && typeof row.emailTemplates === \"object\" ? row.emailTemplates : {};\n return {\n id: String(row.id),\n name: String(row.name ?? \"\"),\n replyTo: str(row.replyTo) ?? \"\",\n debugEmail: str(row.debugEmail),\n refundPolicyText: str(row.refundPolicyText),\n commitmentText: str(row.commitmentText),\n normsText: str(row.normsText),\n emailTemplates: templates as EmailGroup[\"emailTemplates\"],\n };\n}\n","// Payments primitives. Generic Stripe form encoding and webhook authenticity\n// live in @odla-ai/stripe; Chapter keeps only membership-specific readiness,\n// event normalization, and write sets. This preserves Chapter's public exports\n// while making the provider plumbing reusable by every app.\nexport { stripeForm, verifyStripeSignature } from \"@odla-ai/stripe\";\n\n// ── readiness + Stripe wire helpers ──\n\n/** A group row's payment configuration, as far as readiness cares. */\nexport interface PaymentsGroup {\n stripePublishableKey?: string | null;\n stripePriceId?: string | null;\n}\n\n/** Whether a group can take payment: a publishable key + a price id (both on the\n * group row) AND a secret key (the vault). Anything missing drops the join\n * flow's payment step (paymentsReady:false) rather than half-charging. */\nexport function paymentsReady(group: PaymentsGroup, hasSecretKey: boolean): boolean {\n return Boolean(group.stripePublishableKey && group.stripePriceId && hasSecretKey);\n}\n\n/** The Stripe idempotency key for creating an application's subscription — one\n * per application, so a client retry can't orphan a second subscription. */\nexport function subscriptionIdempotencyKey(applicationId: string): string {\n return `sub:${applicationId}`;\n}\n\n/** The db mutationId for a webhook-driven write — exactly-once per Stripe event,\n * so replays are deduped at the db layer. */\nexport function webhookMutationId(eventId: string): string {\n return `stripe:${eventId}`;\n}\n\n// ── webhook normalization (pure; the worker owns the db lookup + writes) ──\n\n/** A raw Stripe event, as far as normalization cares. */\nexport interface StripeEvent {\n id: string;\n type: string;\n data?: { object?: Record<string, unknown> };\n}\n\n/** A normalized, provider-agnostic webhook event. `kind` drives the db write;\n * the application is resolved from `applicationId` (metadata) or `customerId`. */\nexport type WebhookEvent = (\n | { kind: \"gift_paid\"; giftIntentId: string; providerObjectId: string }\n | { kind: \"gift_revoked\"; giftIntentId: string; reason: \"refunded\" | \"canceled\" }\n | { kind: \"first_payment\"; applicationId?: string; customerId?: string; renewalAt?: number }\n | { kind: \"renewal\"; applicationId?: string; customerId?: string; renewalAt?: number }\n | { kind: \"refunded\"; applicationId?: string; customerId?: string }\n | { kind: \"canceled\"; applicationId?: string; customerId?: string }\n | { kind: \"ignored\"; type: string }\n) & { appId?: string; environment?: string };\n\n/** Resolve the application reference on a Stripe object: `applicationId` from\n * metadata (direct, then subscription_details, then nested\n * parent.subscription_details), plus the customer id for the db fallback. */\nexport function findApplicationRef(obj: Record<string, unknown>): {\n applicationId?: string;\n customerId?: string;\n appId?: string;\n environment?: string;\n} {\n const metaOf = (v: unknown): Record<string, unknown> =>\n v && typeof v === \"object\" ? ((v as Record<string, unknown>).metadata as Record<string, unknown>) ?? {} : {};\n const pick = (m: Record<string, unknown>): string | undefined =>\n typeof m.applicationId === \"string\" ? m.applicationId : undefined;\n const candidates = [\n metaOf(obj),\n metaOf(obj.subscription_details),\n metaOf((obj.parent as Record<string, unknown> | undefined)?.subscription_details),\n ];\n const applicationId = candidates.map(pick).find(Boolean);\n const appId = candidates.map((metadata) => typeof metadata.odlaAppId === \"string\" ? metadata.odlaAppId : undefined).find(Boolean);\n const environment = candidates.map((metadata) => typeof metadata.odlaEnvironment === \"string\" ? metadata.odlaEnvironment : undefined).find(Boolean);\n const customerId = typeof obj.customer === \"string\" ? obj.customer : undefined;\n return {\n ...(applicationId ? { applicationId } : {}),\n ...(customerId ? { customerId } : {}),\n ...(appId ? { appId } : {}),\n ...(environment ? { environment } : {}),\n };\n}\n\n/** Resolve gift purchase metadata from direct or invoice subscription metadata. */\nexport function findGiftRef(obj: Record<string, unknown>): { giftIntentId?: string; providerObjectId: string } {\n const metaOf = (value: unknown): Record<string, unknown> =>\n value && typeof value === \"object\" ? ((value as Record<string, unknown>).metadata as Record<string, unknown>) ?? {} : {};\n const pick = (metadata: Record<string, unknown>): string | undefined =>\n typeof metadata.giftIntentId === \"string\" ? metadata.giftIntentId : undefined;\n const parent = obj.parent as Record<string, unknown> | undefined;\n const subscription = obj.subscription_details ?? parent?.subscription_details;\n const giftIntentId = pick(metaOf(obj)) ?? pick(metaOf(subscription));\n const subscriptionId = typeof obj.subscription === \"string\"\n ? obj.subscription\n : typeof (subscription as Record<string, unknown> | undefined)?.subscription === \"string\"\n ? String((subscription as Record<string, unknown>).subscription)\n : undefined;\n return { ...(giftIntentId ? { giftIntentId } : {}), providerObjectId: subscriptionId ?? String(obj.id ?? \"\") };\n}\n\n/** Normalize a verified Stripe event into a {@link WebhookEvent}. `invoice.paid`\n * splits into first_payment vs renewal by `billing_reason`; refunds and\n * cancellations map directly; everything else is ignored (acked, not retried). */\nexport function normalizeWebhookEvent(event: StripeEvent): WebhookEvent {\n const obj = event.data?.object ?? {};\n const gift = findGiftRef(obj);\n if (gift.giftIntentId) {\n if (event.type === \"payment_intent.succeeded\" ||\n (event.type === \"invoice.paid\" && obj.billing_reason === \"subscription_create\")) {\n return { kind: \"gift_paid\", giftIntentId: gift.giftIntentId, providerObjectId: gift.providerObjectId };\n }\n if (event.type === \"charge.refunded\") return { kind: \"gift_revoked\", giftIntentId: gift.giftIntentId, reason: \"refunded\" };\n if (event.type === \"customer.subscription.deleted\") return { kind: \"gift_revoked\", giftIntentId: gift.giftIntentId, reason: \"canceled\" };\n return { kind: \"ignored\", type: event.type };\n }\n const ref = findApplicationRef(obj);\n switch (event.type) {\n case \"invoice.paid\": {\n const lines = ((obj.lines as Record<string, unknown> | undefined)?.data as Array<Record<string, unknown>> | undefined) ?? [];\n const periodEnd = (lines[0]?.period as Record<string, unknown> | undefined)?.end;\n const renewalAt = typeof periodEnd === \"number\" ? periodEnd * 1000 : undefined;\n const kind = obj.billing_reason === \"subscription_create\" ? \"first_payment\" : \"renewal\";\n return { kind, ...ref, ...(renewalAt !== undefined ? { renewalAt } : {}) };\n }\n case \"charge.refunded\":\n return { kind: \"refunded\", ...ref };\n case \"customer.subscription.deleted\":\n return { kind: \"canceled\", ...ref };\n default:\n return { kind: \"ignored\", type: event.type };\n }\n}\n\n// ── webhook write-set builders (the authoritative writers of paid/refunded) ──\n\n/** First-payment patch: advance submitted→paid_pending_vetting (never any other\n * transition) and record the renewal date. Empty when nothing changed, so the\n * caller can skip the write. */\nexport function firstPaymentPatch(currentStatus: string, renewalAt?: number): { status?: \"paid_pending_vetting\"; renewalAt?: number } {\n return {\n ...(currentStatus === \"submitted\" ? { status: \"paid_pending_vetting\" as const } : {}),\n ...(renewalAt !== undefined ? { renewalAt } : {}),\n };\n}\n\n/** Renewal-invoice patch: just the new renewal date. */\nexport function renewalPatch(renewalAt: number): { renewalAt: number } {\n return { renewalAt };\n}\n\n/** Refund patch — the SOLE writer of status \"refunded\" (the admin refund route\n * issues the Stripe refund but never sets this; the webhook does). */\nexport function refundedPatch(): { status: \"refunded\" } {\n return { status: \"refunded\" };\n}\n\n/** Subscription-cancellation patch. */\nexport function canceledPatch(): { canceled: true } {\n return { canceled: true };\n}\n","/** Current wire version for parent-authored admission decisions. */\nexport const ADMISSION_GRANTS_SCHEMA_VERSION = 1 as const;\n/** Dedicated signed Parent → Chapter delivery endpoint. */\nexport const ADMISSION_GRANTS_PATH = \"/api/admission-grants\" as const;\n\n/** Whether an exact email can skip or must retain the Chapter interview. */\nexport type AdmissionDecision = \"waive_interview\" | \"require_interview\";\n\n/** One bounded admission decision. Email is PII and never enters public config. */\nexport interface AdmissionGrantInput {\n id: string;\n email: string;\n decision: AdmissionDecision;\n note?: string;\n expiresAt?: number;\n}\n\n/** Complete desired Parent state for one Chapter and environment. */\nexport interface AdmissionGrantDocument {\n schemaVersion: typeof ADMISSION_GRANTS_SCHEMA_VERSION;\n revision: number;\n generatedAt: number;\n source: { appId: string; actor: string };\n target: { chapterId: string; environment: string };\n grants: readonly AdmissionGrantInput[];\n}\n\n/** Canonical desired-state document paired with its integrity digest. */\nexport interface AdmissionGrantEnvelope {\n digest: string;\n document: AdmissionGrantDocument;\n}\n\n/** Chapter acknowledgement for an accepted or idempotently replayed revision. */\nexport interface AdmissionGrantReceipt {\n ok: true;\n target: { chapterId: string; environment: string };\n revision: number;\n digest: string;\n status: \"accepted\" | \"replayed\";\n acknowledgedAt: number;\n}\n\n/** Stable machine-readable rejection reasons returned by a Chapter receiver. */\nexport type AdmissionGrantRejection =\n | \"invalid_document\"\n | \"invalid_digest\"\n | \"wrong_source\"\n | \"wrong_target\"\n | \"wrong_environment\"\n | \"stale_revision\"\n | \"conflicting_revision\"\n | \"materialization_failed\";\n","const encoder = new TextEncoder();\n\nfunction canonicalValue(value: unknown): string {\n if (value === null || typeof value === \"boolean\" || typeof value === \"number\" || typeof value === \"string\") {\n return JSON.stringify(value);\n }\n if (Array.isArray(value)) return `[${value.map(canonicalValue).join(\",\")}]`;\n if (typeof value !== \"object\") throw new TypeError(\"signup control contains an unsupported value\");\n const record = value as Record<string, unknown>;\n const entries = Object.keys(record).sort().flatMap((key) => {\n const item = record[key];\n return item === undefined ? [] : [`${JSON.stringify(key)}:${canonicalValue(item)}`];\n });\n return `{${entries.join(\",\")}}`;\n}\n\n/** Serialize JSON-like signup state with recursively sorted object keys. */\nexport function canonicalSignupControl(value: unknown): string {\n return canonicalValue(value);\n}\n\n/** Compute the protocol's canonical SHA-256 digest for desired signup state. */\nexport async function signupControlDigest(document: unknown): Promise<string> {\n const digest = await crypto.subtle.digest(\"SHA-256\", encoder.encode(canonicalSignupControl(document)));\n return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\n/** Pair one desired-state document with its canonical digest for delivery. */\nexport async function createSignupControlEnvelope(document: import(\"./signup-control-contract\").SignupControlDocument) {\n return { document, digest: await signupControlDigest(document) };\n}\n","import type {\n AdmissionDecision,\n AdmissionGrantDocument,\n AdmissionGrantEnvelope,\n AdmissionGrantInput,\n} from \"./admission-grants-contract\";\nimport { ADMISSION_GRANTS_SCHEMA_VERSION } from \"./admission-grants-contract\";\nimport type { ChapterDb, DbOp } from \"./types\";\nimport { signupControlDigest } from \"./signup-control-canonical\";\nimport { normalizeChapterEmail } from \"./email-identity\";\n\nconst ID = /^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/;\nconst MAX_GRANTS = 2_000;\nconst MAX_NOTE = 2_000;\nconst EMAIL_RE = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/;\nconst isAdmissionEmail = (value: string): boolean => EMAIL_RE.test(value);\n\n/** Exact email natural key: trim and lowercase, with no provider alias rules. */\nexport function normalizeAdmissionEmail(email: string): string {\n return normalizeChapterEmail(email);\n}\n\n/** Validated normalized admission document or all contract errors. */\nexport type AdmissionGrantValidation =\n | { ok: true; value: AdmissionGrantDocument }\n | { ok: false; errors: readonly string[] };\n\n/** Validate and normalize a complete Parent admission document. */\nexport function validateAdmissionGrantDocument(input: unknown): AdmissionGrantValidation {\n const errors: string[] = [];\n const root = input && typeof input === \"object\" ? input as Record<string, unknown> : {};\n if (root.schemaVersion !== ADMISSION_GRANTS_SCHEMA_VERSION) errors.push(\"document.schemaVersion must be 1\");\n const revision = Number(root.revision);\n const generatedAt = Number(root.generatedAt);\n if (!Number.isSafeInteger(revision) || revision < 1) errors.push(\"document.revision must be a positive integer\");\n if (!Number.isFinite(generatedAt) || generatedAt <= 0) errors.push(\"document.generatedAt must be epoch milliseconds\");\n const source = root.source && typeof root.source === \"object\" ? root.source as Record<string, unknown> : {};\n const target = root.target && typeof root.target === \"object\" ? root.target as Record<string, unknown> : {};\n const sourceId = typeof source.appId === \"string\" ? source.appId : \"\";\n const sourceActor = typeof source.actor === \"string\" ? source.actor.trim() : \"\";\n const chapterId = typeof target.chapterId === \"string\" ? target.chapterId : \"\";\n const environment = typeof target.environment === \"string\" ? target.environment : \"\";\n if (!ID.test(sourceId)) errors.push(\"document.source.appId must be an identifier\");\n if (!sourceActor || sourceActor.length > 256) errors.push(\"document.source.actor must be 1-256 characters\");\n if (!ID.test(chapterId)) errors.push(\"document.target.chapterId must be an identifier\");\n if (!ID.test(environment)) errors.push(\"document.target.environment must be an identifier\");\n if (!Array.isArray(root.grants)) errors.push(\"document.grants must be an array\");\n const rawGrants = Array.isArray(root.grants) ? root.grants : [];\n if (rawGrants.length > MAX_GRANTS) errors.push(`document.grants supports at most ${MAX_GRANTS} entries`);\n const grants: AdmissionGrantInput[] = [];\n const seenIds = new Set<string>();\n const seenEmails = new Set<string>();\n for (const [index, raw] of rawGrants.slice(0, MAX_GRANTS).entries()) {\n const grant = raw && typeof raw === \"object\" ? raw as Record<string, unknown> : {};\n const id = typeof grant.id === \"string\" ? grant.id : \"\";\n const email = typeof grant.email === \"string\" ? grant.email.trim() : \"\";\n const normalized = normalizeAdmissionEmail(email);\n const decision = grant.decision;\n const note = typeof grant.note === \"string\" ? grant.note.trim() : undefined;\n const expiresAt = grant.expiresAt === undefined ? undefined : Number(grant.expiresAt);\n if (!ID.test(id)) errors.push(`document.grants[${index}].id must be an identifier`);\n if (seenIds.has(id)) errors.push(`document.grants repeats id \"${id}\"`);\n if (!isAdmissionEmail(normalized)) errors.push(`document.grants[${index}].email must be valid`);\n if (seenEmails.has(normalized)) errors.push(`document.grants repeats email \"${normalized}\"`);\n if (decision !== \"waive_interview\" && decision !== \"require_interview\") {\n errors.push(`document.grants[${index}].decision is invalid`);\n }\n if (note && note.length > MAX_NOTE) errors.push(`document.grants[${index}].note is too long`);\n if (expiresAt !== undefined && (!Number.isFinite(expiresAt) || expiresAt <= 0)) {\n errors.push(`document.grants[${index}].expiresAt must be epoch milliseconds`);\n }\n seenIds.add(id);\n seenEmails.add(normalized);\n grants.push({\n id,\n email,\n decision: decision as AdmissionDecision,\n ...(note ? { note } : {}),\n ...(expiresAt !== undefined ? { expiresAt } : {}),\n });\n }\n if (errors.length) return { ok: false, errors };\n return {\n ok: true,\n value: {\n schemaVersion: ADMISSION_GRANTS_SCHEMA_VERSION,\n revision,\n generatedAt,\n source: { appId: sourceId, actor: sourceActor },\n target: { chapterId, environment },\n grants,\n },\n };\n}\n\n/** Pair a validated desired-state document with its canonical digest. */\nexport async function createAdmissionGrantEnvelope(document: AdmissionGrantDocument): Promise<AdmissionGrantEnvelope> {\n const checked = validateAdmissionGrantDocument(document);\n if (!checked.ok) throw new TypeError(`Invalid admission grant document: ${checked.errors.join(\"; \")}`);\n return { document: checked.value, digest: await signupControlDigest(checked.value) };\n}\n\n/** Materialized local or Parent admission decision stored by a Chapter. */\nexport interface AdmissionGrantRow {\n id: string;\n sourceGrantId: string;\n sourceScope: \"local\" | \"parent\";\n sourceId: string;\n targetId: string;\n email: string;\n emailNormalized: string;\n decision: AdmissionDecision;\n active: boolean;\n createdAt: number;\n note?: string;\n expiresAt?: number;\n revokedAt?: number;\n consumedAt?: number;\n consumedApplicationId?: string;\n}\n\nconst rows = (value: unknown): Array<Record<string, unknown>> => Array.isArray(value) ? value : [];\n\nfunction asGrant(row: Record<string, unknown>): AdmissionGrantRow | null {\n if (typeof row.id !== \"string\" || typeof row.emailNormalized !== \"string\") return null;\n if (row.sourceScope !== \"local\" && row.sourceScope !== \"parent\") return null;\n if (row.decision !== \"waive_interview\" && row.decision !== \"require_interview\") return null;\n return row as unknown as AdmissionGrantRow;\n}\n\n/** Resolve the effective current decision. Local rows always outrank Parent rows. */\nexport async function findAdmissionGrant(\n db: ChapterDb,\n targetId: string,\n email: string,\n now: number,\n): Promise<AdmissionGrantRow | null> {\n const emailNormalized = normalizeAdmissionEmail(email);\n if (!isAdmissionEmail(emailNormalized)) return null;\n const result = await db.query({ admissionGrants: { $: { where: { emailNormalized }, limit: 100 } } });\n const active = rows(result.admissionGrants)\n .map(asGrant)\n .filter((grant): grant is AdmissionGrantRow => Boolean(\n grant && grant.targetId === targetId && grant.active === true && !grant.revokedAt &&\n (!grant.expiresAt || grant.expiresAt > now) && !grant.consumedApplicationId,\n ))\n .sort((a, b) => {\n const scope = Number(b.sourceScope === \"local\") - Number(a.sourceScope === \"local\");\n return scope || b.createdAt - a.createdAt;\n });\n return active[0] ?? null;\n}\n\n/** Stored receipt for one signed Parent admission revision. */\nexport interface AdmissionGrantRevisionRow {\n id: string;\n sourceId: string;\n targetId: string;\n environment: string;\n revision: number;\n digest: string;\n active: boolean;\n receivedAt: number;\n}\n\nasync function hasAdmissionRevision(\n db: ChapterDb,\n sourceId: string,\n targetId: string,\n environment: string,\n): Promise<boolean> {\n const where = { sourceId, targetId, environment };\n if (db.aggregate) {\n return Number((await db.aggregate(\"admissionGrantRevisions\", { count: true }, { where })).count ?? 0) > 0;\n }\n const found = await db.query({ admissionGrantRevisions: {} });\n return rows(found.admissionGrantRevisions).some((row) =>\n row.sourceId === sourceId && row.targetId === targetId && row.environment === environment);\n}\n\n/** Read the newest received revision without issuing an ordered query over empty history. */\nexport async function loadLatestAdmissionRevision(\n db: ChapterDb,\n sourceId: string,\n targetId: string,\n environment: string,\n): Promise<AdmissionGrantRevisionRow | null> {\n if (!await hasAdmissionRevision(db, sourceId, targetId, environment)) return null;\n const result = await db.query({ admissionGrantRevisions: { $: {\n where: { sourceId, targetId, environment }, order: { revision: \"desc\" }, limit: 1,\n } } });\n const row = rows(result.admissionGrantRevisions)\n .sort((a, b) => Number(b.revision ?? 0) - Number(a.revision ?? 0))[0];\n return row ? row as unknown as AdmissionGrantRevisionRow : null;\n}\n\n/** Replace only Parent-authored rows; local Chapter decisions remain untouched. */\nexport async function materializeAdmissionGrants(\n db: ChapterDb,\n envelope: AdmissionGrantEnvelope,\n previous: AdmissionGrantRevisionRow | null,\n receivedAt: number,\n): Promise<void> {\n const { document, digest } = envelope;\n const current = rows((await db.query({ admissionGrants: { $: {\n where: { sourceScope: \"parent\", sourceId: document.source.appId, targetId: document.target.chapterId },\n limit: MAX_GRANTS,\n } } })).admissionGrants);\n const incomingIds = new Set(document.grants.map((grant) => `admission:parent:${document.source.appId}:${grant.id}`));\n const ops: DbOp[] = [];\n for (const row of current) {\n const id = String(row.id ?? \"\");\n if (id && !incomingIds.has(id)) ops.push({ t: \"update\", ns: \"admissionGrants\", id, attrs: {\n active: false, revokedAt: receivedAt, revokedBy: document.source.actor,\n updatedAt: receivedAt, updatedBy: document.source.actor,\n } });\n }\n for (const grant of document.grants) {\n const id = `admission:parent:${document.source.appId}:${grant.id}`;\n const existing = current.find((row) => row.id === id);\n ops.push({ t: \"update\", ns: \"admissionGrants\", id, attrs: {\n id,\n sourceGrantId: grant.id,\n sourceScope: \"parent\",\n sourceId: document.source.appId,\n targetId: document.target.chapterId,\n email: grant.email,\n emailNormalized: normalizeAdmissionEmail(grant.email),\n decision: grant.decision,\n ...(grant.note ? { note: grant.note } : {}),\n ...(grant.expiresAt ? { expiresAt: grant.expiresAt } : {}),\n active: true,\n sourceRevision: document.revision,\n createdAt: Number(existing?.createdAt ?? receivedAt),\n createdBy: String(existing?.createdBy ?? document.source.actor),\n updatedAt: receivedAt,\n updatedBy: document.source.actor,\n } });\n const retract = [\n ...(!grant.note && existing?.note !== undefined ? [\"note\"] : []),\n ...(grant.expiresAt === undefined && existing?.expiresAt !== undefined ? [\"expiresAt\"] : []),\n ];\n if (retract.length) ops.push({ t: \"retract\", ns: \"admissionGrants\", id, attrs: retract });\n }\n if (previous?.active) ops.push({ t: \"update\", ns: \"admissionGrantRevisions\", id: previous.id, attrs: { active: false } });\n const revisionId = `admission-revision:${document.source.appId}:${document.target.environment}:${document.revision}`;\n ops.push({ t: \"update\", ns: \"admissionGrantRevisions\", id: revisionId, attrs: {\n id: revisionId,\n sourceId: document.source.appId,\n targetId: document.target.chapterId,\n environment: document.target.environment,\n revision: document.revision,\n digest,\n active: true,\n receivedAt,\n } });\n await db.transact(ops, { mutationId: `admission-grants:${document.source.appId}:${document.target.environment}:${document.revision}:${digest}` });\n}\n","import { canBook } from \"./pipeline\";\nimport type { ResolvedPipeline } from \"./types\";\n\n/** Canonical next action or browser-visible step after application submission. */\nexport type JoinContinuation = \"payment\" | \"paymentPending\" | \"booking\" | \"approve\" | \"accepted\";\n\n/** One server-side decision for submit, resume, and payment completion. */\nexport function resolveJoinContinuation(input: {\n status: string;\n initialStatus: string;\n pipeline: ResolvedPipeline;\n payable: boolean;\n subscriptionStarted: boolean;\n interviewWaived: boolean;\n}): JoinContinuation | null {\n if (input.status === \"approved\") return \"accepted\";\n if (input.interviewWaived) {\n if (!input.payable) return \"approve\";\n if (input.status === input.initialStatus) {\n return input.subscriptionStarted ? \"paymentPending\" : \"payment\";\n }\n return \"approve\";\n }\n if (!input.payable) return \"booking\";\n if (input.status === input.initialStatus) {\n return input.subscriptionStarted ? \"paymentPending\" : \"payment\";\n }\n if (canBook(input.status, input.pipeline)) return \"booking\";\n return null;\n}\n","/** Current nested gift-catalog version inside signup-control. */\nexport const GIFT_OFFER_CATALOG_VERSION = 1 as const;\n/** Maximum signed gift SKUs accepted in one catalog revision. */\nexport const MAX_GIFT_OFFERS = 20;\n\n/** Membership tier or standalone entitlement fulfilled by redemption. */\nexport type GiftOfferTarget =\n | { type: \"tier\"; tierId: string }\n | { type: \"entitlement\"; entitlementKey: string };\n\n/** Server-authored gift SKU; provider identifiers never reach public config. */\nexport interface GiftOffer {\n id: string;\n target: GiftOfferTarget;\n billingMode: \"one_time\" | \"subscription\";\n stripePriceId: string;\n priceCents: number;\n currency: string;\n redemptionLifetimeHours: number;\n activeFrom?: number;\n activeUntil?: number;\n title: string;\n description: string;\n ctaLabel: string;\n}\n\n/** Versioned bounded collection delegated through signed signup control. */\nexport interface GiftOfferCatalog {\n schemaVersion: typeof GIFT_OFFER_CATALOG_VERSION;\n offers: readonly GiftOffer[];\n}\n\n/** Provider-free gift offer shape rendered by Chapter and exact CMS previews. */\nexport type PublicGiftOffer = Omit<GiftOffer, \"stripePriceId\" | \"target\">;\n\n/** Result of validating and normalizing an untrusted gift catalog. */\nexport type GiftOfferValidation =\n | { ok: true; value: GiftOfferCatalog }\n | { ok: false; errors: readonly string[] };\n\nconst ID = /^[a-z][a-z0-9-]{1,79}$/;\nconst PRICE = /^price_[A-Za-z0-9]{12,}$/;\nconst CURRENCY = /^[a-z]{3}$/;\nconst record = (value: unknown): Record<string, unknown> | null =>\n value && typeof value === \"object\" && !Array.isArray(value) ? value as Record<string, unknown> : null;\nconst text = (value: unknown, path: string, errors: string[], max: number): string => {\n if (typeof value !== \"string\" || !value.trim()) { errors.push(`${path} is required`); return \"\"; }\n if (value.trim().length > max) errors.push(`${path} must be at most ${max} characters`);\n return value.trim();\n};\n\n/** Validate and normalize gift offers against the same document's tier ids. */\nexport function validateGiftOfferCatalog(input: unknown, tierIds: ReadonlySet<string>): GiftOfferValidation {\n const errors: string[] = [];\n const root = record(input);\n if (!root) return { ok: false, errors: [\"document.giftOffers must be an object\"] };\n for (const key of Object.keys(root)) if (key !== \"schemaVersion\" && key !== \"offers\") errors.push(`document.giftOffers.${key} is not supported`);\n if (root.schemaVersion !== GIFT_OFFER_CATALOG_VERSION) errors.push(\"document.giftOffers.schemaVersion must be 1\");\n if (!Array.isArray(root.offers)) errors.push(\"document.giftOffers.offers must be an array\");\n const rawOffers = Array.isArray(root.offers) ? root.offers : [];\n if (rawOffers.length > MAX_GIFT_OFFERS) errors.push(`document.giftOffers.offers supports at most ${MAX_GIFT_OFFERS} entries`);\n const ids = new Set<string>();\n const offers: GiftOffer[] = [];\n for (const [index, raw] of rawOffers.slice(0, MAX_GIFT_OFFERS).entries()) {\n const path = `document.giftOffers.offers[${index}]`;\n const item = record(raw);\n if (!item) { errors.push(`${path} must be an object`); continue; }\n const allowed = new Set([\"id\", \"target\", \"billingMode\", \"stripePriceId\", \"priceCents\", \"currency\", \"redemptionLifetimeHours\", \"activeFrom\", \"activeUntil\", \"title\", \"description\", \"ctaLabel\"]);\n for (const key of Object.keys(item)) if (!allowed.has(key)) errors.push(`${path}.${key} is not supported`);\n const id = text(item.id, `${path}.id`, errors, 80);\n if (id && !ID.test(id)) errors.push(`${path}.id must be a lowercase kebab-case id`);\n if (ids.has(id)) errors.push(`${path}.id duplicates \"${id}\"`);\n ids.add(id);\n const targetRaw = record(item.target);\n let target: GiftOfferTarget = { type: \"entitlement\", entitlementKey: \"invalid\" };\n if (targetRaw?.type === \"tier\") {\n const tierId = text(targetRaw.tierId, `${path}.target.tierId`, errors, 80);\n if (!tierIds.has(tierId)) errors.push(`${path}.target.tierId must reference a declared tier`);\n target = { type: \"tier\", tierId };\n } else if (targetRaw?.type === \"entitlement\") {\n const entitlementKey = text(targetRaw.entitlementKey, `${path}.target.entitlementKey`, errors, 80);\n if (entitlementKey && !ID.test(entitlementKey)) errors.push(`${path}.target.entitlementKey must be a lowercase kebab-case id`);\n target = { type: \"entitlement\", entitlementKey };\n } else errors.push(`${path}.target.type must be tier or entitlement`);\n if (item.billingMode !== \"one_time\" && item.billingMode !== \"subscription\") errors.push(`${path}.billingMode must be one_time or subscription`);\n const stripePriceId = text(item.stripePriceId, `${path}.stripePriceId`, errors, 128);\n if (stripePriceId && !PRICE.test(stripePriceId)) errors.push(`${path}.stripePriceId must be a real Stripe Price id`);\n if (!Number.isSafeInteger(item.priceCents) || Number(item.priceCents) < 1 || Number(item.priceCents) > 100_000_000) errors.push(`${path}.priceCents must be an integer from 1 to 100,000,000`);\n const currency = typeof item.currency === \"string\" ? item.currency.trim().toLowerCase() : \"\";\n if (!CURRENCY.test(currency)) errors.push(`${path}.currency must be a lowercase ISO currency code`);\n const lifetime = Number(item.redemptionLifetimeHours);\n if (!Number.isSafeInteger(lifetime) || lifetime < 1 || lifetime > 8_760) errors.push(`${path}.redemptionLifetimeHours must be an integer from 1 to 8760`);\n const activeFrom = item.activeFrom === undefined ? undefined : Number(item.activeFrom);\n const activeUntil = item.activeUntil === undefined ? undefined : Number(item.activeUntil);\n if (activeFrom !== undefined && (!Number.isSafeInteger(activeFrom) || activeFrom < 1)) errors.push(`${path}.activeFrom must be epoch milliseconds`);\n if (activeUntil !== undefined && (!Number.isSafeInteger(activeUntil) || activeUntil < 1)) errors.push(`${path}.activeUntil must be epoch milliseconds`);\n if (activeFrom !== undefined && activeUntil !== undefined && activeUntil <= activeFrom) errors.push(`${path}.activeUntil must follow activeFrom`);\n offers.push({\n id, target, billingMode: item.billingMode as GiftOffer[\"billingMode\"], stripePriceId,\n priceCents: Number(item.priceCents), currency, redemptionLifetimeHours: lifetime,\n ...(activeFrom !== undefined ? { activeFrom } : {}), ...(activeUntil !== undefined ? { activeUntil } : {}),\n title: text(item.title, `${path}.title`, errors, 160), description: text(item.description, `${path}.description`, errors, 2_000),\n ctaLabel: text(item.ctaLabel, `${path}.ctaLabel`, errors, 120),\n });\n }\n return errors.length ? { ok: false, errors } : { ok: true, value: { schemaVersion: 1, offers } };\n}\n\n/** Whether an offer is active at an exact server time. */\nexport const giftOfferActive = (offer: GiftOffer, now: number): boolean =>\n (!offer.activeFrom || offer.activeFrom <= now) && (!offer.activeUntil || offer.activeUntil > now);\n\n/** Public provider-free active catalog projection. */\nexport function publicGiftOffers(catalog: GiftOfferCatalog | undefined, now: number): PublicGiftOffer[] {\n return (catalog?.offers ?? []).filter((offer) => giftOfferActive(offer, now)).map(({ stripePriceId: _stripe, target: _target, ...offer }) => offer);\n}\n\n/** Resolve one currently active server-authoritative offer. */\nexport function findGiftOffer(catalog: GiftOfferCatalog | undefined, offerId: string, now: number): GiftOffer | null {\n return catalog?.offers.find((offer) => offer.id === offerId && giftOfferActive(offer, now)) ?? null;\n}\n","// Leader → follower projection of a deliberately allowlisted CRM field set.\n//\n// Invariants (package-enforced so no site re-derives them):\n// - One-way: the chapter never writes back to the hub through this path.\n// - Idempotent: every received record carries the leader's stable site +\n// record identity. A structured crm_record_origin row maps that identity to\n// the local CRM record, so a re-share updates instead of duplicating even\n// after an email/domain changes. Legacy tags remain as a migration bridge.\n// - Natural-key convergence: a person unifies by primary email and a business\n// by its configured domain slot (then name), so an arriving applicant and a\n// prior leader share compose into one person.\n// - Operational state stays local. Pipeline/account/billing state is not copied\n// into another site's authority; the push transfers the shared record fields.\n//\n// Reuses @odla-ai/crm's record ops (full validation via crm.prepare), driven by\n// the resolved chapter CRM engine + the structural ChapterDb.\nimport {\n createRecord,\n getRecordByOrigin,\n updateRecord,\n upsertRecordOrigin,\n} from \"@odla-ai/crm\";\nimport type { Crm, CrmRecord } from \"@odla-ai/crm\";\nimport type { ChapterDb, ResolvedNetworkTarget } from \"./types\";\nimport {\n DEFAULT_SHARE_FIELDS,\n type NormalizedSharedRecord,\n type ProjectionDeps,\n type SharedBusiness,\n type SharedPerson,\n type SharedRecord,\n} from \"./network-contract\";\nexport { DEFAULT_SHARE_FIELDS } from \"./network-contract\";\nexport type {\n NetworkRollup, NetworkRollupTarget,\n NetworkSnapshot,\n ProjectionDeps,\n SharedBusiness,\n SharedPerson,\n SharedRecord,\n SharedRecordV1,\n SharedRecordV2,\n} from \"./network-contract\";\n\n/** Map a shared prospect to a crm `person` input (only the fields the default\n * person type accepts). Name falls back to first+last, then the email. */\nexport function sharedPersonInput(person: SharedPerson): Record<string, unknown> {\n const email = person.email.toLowerCase();\n const fullName = [person.firstName, person.lastName].filter(Boolean).join(\" \").trim();\n const input: Record<string, unknown> = { name: person.name ?? fullName ?? email, email };\n if (input.name === \"\") input.name = email;\n if (person.firstName) input.firstName = person.firstName;\n if (person.lastName) input.lastName = person.lastName;\n if (person.phone) input.phone = person.phone;\n if (person.linkedin) input.linkedin = person.linkedin;\n return input;\n}\n\nfunction shortHash(value: string): string {\n let a = 0x811c9dc5;\n let b = 0x9e3779b9;\n for (let i = 0; i < value.length; i += 1) {\n const n = value.charCodeAt(i);\n a = Math.imul(a ^ n, 0x01000193);\n b = Math.imul(b ^ n, 0x85ebca6b);\n }\n return `${(a >>> 0).toString(36)}${(b >>> 0).toString(36)}`;\n}\n\n/** Backward-compatible display tag retained while structured origin rows are\n * the durable leader-id → local-record mapping. */\nexport function networkSourceTag(type: string, hubRecordId: string, sourceId?: string): string {\n const typeKey = type.toLowerCase();\n const readable = /^[a-z0-9_-]+$/.test(hubRecordId);\n const prefix = sourceId ? `network:${sourceId.toLowerCase()}:${typeKey}` : `network:${typeKey}`;\n const raw = `${prefix}:${hubRecordId}`;\n if (readable && raw.length <= 64) return raw;\n return `network:${typeKey.slice(0, 16)}:${shortHash(`${sourceId ?? \"\"}\\u0000${type}\\u0000${hubRecordId}`)}`;\n}\n\n/** Normalize the backwards-compatible person/business shapes into the versioned\n * generic record envelope the receiver writes. */\nexport function normalizeSharedRecord(\n record: SharedPerson | SharedBusiness | SharedRecord,\n fallbackSourceId = \"legacy-source\",\n): NormalizedSharedRecord {\n if (\"input\" in record && record.version === 2) {\n return {\n version: 2,\n sourceId: record.source.siteId,\n sourceRecordId: record.source.recordId,\n type: record.type,\n input: record.input,\n };\n }\n if (\"input\" in record) {\n return {\n version: 1,\n sourceId: fallbackSourceId,\n sourceRecordId: record.hubRecordId,\n type: record.type,\n input: record.input,\n };\n }\n if (\"type\" in record && record.type === \"company\") {\n const input: Record<string, unknown> = { name: record.name };\n for (const key of [\"domain\", \"industry\", \"location\", \"linkedin\", \"notes\"] as const) {\n if (record[key]) input[key] = record[key];\n }\n return {\n version: 1,\n sourceId: fallbackSourceId,\n sourceRecordId: record.hubRecordId,\n type: \"company\",\n input,\n };\n }\n return {\n version: 1,\n sourceId: fallbackSourceId,\n sourceRecordId: record.hubRecordId,\n type: \"person\",\n input: sharedPersonInput(record),\n };\n}\n\n/** Build the allowlisted payload sent from one leader CRM record to a target.\n * A target with an explicit `fields` map only accepts the types it lists. */\nexport function sharedRecordFromCrm(\n crm: Crm,\n record: CrmRecord,\n target: ResolvedNetworkTarget,\n sourceId?: string,\n): SharedRecord {\n if (target.fields && !target.fields[record.type]) {\n throw new Error(`${target.name} does not accept \"${record.type}\" records`);\n }\n const def = crm.type(record.type);\n const fields = target.fields?.[record.type] ?? DEFAULT_SHARE_FIELDS[record.type];\n if (!fields) {\n throw new Error(`${target.name} requires an explicit field allowlist for \"${record.type}\" records`);\n }\n const nameField = def.nameField ?? \"name\";\n const input: Record<string, unknown> = {};\n for (const field of new Set([nameField, ...fields])) {\n const value = record.fields?.[field];\n if (value !== undefined) input[field] = value;\n }\n if (input[nameField] === undefined) input[nameField] = record.name;\n return sourceId\n ? { version: 2, source: { siteId: sourceId, recordId: record.id }, type: record.type, input }\n : { version: 1, type: record.type, hubRecordId: record.id, input };\n}\n\n// Resolve an existing crm_record person by lowercased primaryEmail and update it,\n// else create one under the given mutationId. The shared core of every one-way\n// person projection (hub share, arriving applicant).\nasync function upsertPerson(\n deps: ProjectionDeps,\n opts: { email: string; input: Record<string, unknown>; mutationId: string },\n): Promise<{ recordId: string }> {\n const email = opts.email.toLowerCase();\n const crmDeps = { crm: deps.crm, db: deps.db as never, now: deps.now, newId: deps.newId };\n const { crm_record } = await deps.db.query({ crm_record: { $: { where: { type: \"person\", primaryEmail: email }, limit: 1 } } });\n const existing = crm_record?.[0];\n if (existing && typeof existing.id === \"string\") {\n await updateRecord(crmDeps, { id: existing.id, input: opts.input });\n return { recordId: existing.id };\n }\n const created = await createRecord(crmDeps, { type: \"person\", input: opts.input, mutationId: opts.mutationId });\n return { recordId: created.id };\n}\n\nasync function findSharedRecord(\n deps: ProjectionDeps,\n record: NormalizedSharedRecord,\n tag: string,\n): Promise<Record<string, unknown> | undefined> {\n const structured = await getRecordByOrigin(\n { crm: deps.crm, db: deps.db as never, now: deps.now, newId: deps.newId },\n record.sourceId,\n record.sourceRecordId,\n );\n if (structured) return structured as unknown as Record<string, unknown>;\n const mapped = await deps.db.query({ crm_tag: { $: { where: { tag }, limit: 1 } } });\n const mappedId = mapped.crm_tag?.[0]?.recordId;\n if (typeof mappedId === \"string\") {\n const found = await deps.db.query({ crm_record: { $: { where: { id: mappedId }, limit: 1 } } });\n if (found.crm_record?.[0]) return found.crm_record[0];\n }\n const def = deps.crm.type(record.type);\n const emailField = def.emailField;\n if (emailField && typeof record.input[emailField] === \"string\") {\n const primaryEmail = record.input[emailField].toLowerCase();\n const found = await deps.db.query({\n crm_record: { $: { where: { type: record.type, primaryEmail }, limit: 1 } },\n });\n if (found.crm_record?.[0]) return found.crm_record[0];\n }\n const domain = record.input.domain;\n const domainSlot = def.fields.domain?.slot;\n if (typeof domain === \"string\" && domainSlot) {\n const found = await deps.db.query({\n crm_record: { $: { where: { type: record.type, [domainSlot]: domain }, limit: 1 } },\n });\n if (found.crm_record?.[0]) return found.crm_record[0];\n }\n const nameField = def.nameField ?? \"name\";\n const name = record.input[nameField];\n if (record.type === \"company\" && typeof name === \"string\" && name.trim()) {\n const found = await deps.db.query({\n crm_record: { $: { where: { type: record.type, name: name.trim() }, limit: 1 } },\n });\n if (found.crm_record?.[0]) return found.crm_record[0];\n }\n return undefined;\n}\n\n/**\n * Upsert a leader-shared CRM record into this follower. Accepts the original\n * person wire shape plus the versioned generic shape. Re-shares resolve through\n * a durable provenance tag; people/businesses also converge by natural key.\n */\nexport async function projectSharedRecord(\n deps: ProjectionDeps,\n shared: SharedPerson | SharedBusiness | SharedRecord,\n options: { sourceId?: string; sourceUrl?: string } = {},\n): Promise<{ recordId: string }> {\n const record = normalizeSharedRecord(shared, options.sourceId);\n if (!record.type.trim() || !record.sourceId.trim() || !record.sourceRecordId.trim()) {\n throw new Error(\"type, source site id, and source record id must be non-empty\");\n }\n if (options.sourceId && options.sourceId !== record.sourceId) {\n throw new Error(\"signed sender does not match payload source\");\n }\n const tag = networkSourceTag(record.type, record.sourceRecordId, record.version === 2 ? record.sourceId : undefined);\n const crmDeps = { crm: deps.crm, db: deps.db as never, now: deps.now, newId: deps.newId };\n const existing = await findSharedRecord(deps, record, tag);\n let recordId: string;\n if (existing && typeof existing.id === \"string\") {\n // Do not use one permanent mutation id for updates: a later leader edit is a\n // new desired state and must not be mistaken for a retry of an older push.\n await updateRecord(crmDeps, { id: existing.id, input: record.input });\n recordId = existing.id;\n } else {\n // A deterministic id makes concurrent first deliveries converge even when\n // both requests observe no provenance row before either transaction lands.\n recordId = `network_${shortHash(`${record.sourceId}\\u0000${record.type}\\u0000${record.sourceRecordId}`)}`;\n await createRecord({ ...crmDeps, newId: () => recordId }, {\n type: record.type,\n input: record.input,\n mutationId: `share-create:${tag}`,\n });\n }\n await deps.db.transact(\n [{ t: \"update\", ns: \"crm_tag\", id: tag, attrs: { key: `${recordId}:${tag}`, recordId, tag, createdAt: deps.now() } }],\n { mutationId: `share-map:${tag}:${recordId}` },\n );\n await upsertRecordOrigin(crmDeps, {\n recordId,\n sourceId: record.sourceId,\n sourceRecordId: record.sourceRecordId,\n ...(options.sourceUrl ? { sourceUrl: options.sourceUrl } : {}),\n payloadVersion: record.version,\n });\n return { recordId };\n}\n\n/** An arriving applicant, as far as the CRM projection cares. `extra` carries the\n * site-configured `crmFields` (values from the application), merged on top of the\n * built-in identity/contact set. */\nexport interface Applicant {\n applicationId: string;\n email: string;\n firstName?: string;\n lastName?: string;\n phone?: string;\n linkedin?: string;\n extra?: Record<string, unknown>;\n}\n\n/**\n * Project an arriving applicant into this chapter's `crm_record`, so a new\n * application shows up in the CRM immediately, unified by email with any prior\n * record. Idempotent per application (`apply:${applicationId}`). Best-effort at\n * the call site — a projection failure never fails the application.\n *\n * `extra` fields (a site's `crmFields`) are merged on top of the base person. If\n * an extra field is not on the crm person type, crm validation throws — so the\n * projection retries with the base person alone, ensuring a misconfigured\n * enrichment never silently drops the applicant from the CRM entirely.\n */\nexport async function projectApplicant(deps: ProjectionDeps, applicant: Applicant): Promise<{ recordId: string }> {\n const base = sharedPersonInput({\n email: applicant.email,\n firstName: applicant.firstName,\n lastName: applicant.lastName,\n phone: applicant.phone,\n linkedin: applicant.linkedin,\n hubRecordId: applicant.applicationId,\n });\n const mutationId = `apply:${applicant.applicationId}`;\n const extra = applicant.extra ?? {};\n if (Object.keys(extra).length === 0) return upsertPerson(deps, { email: applicant.email, input: base, mutationId });\n try {\n return await upsertPerson(deps, { email: applicant.email, input: { ...base, ...extra }, mutationId });\n } catch {\n return upsertPerson(deps, { email: applicant.email, input: base, mutationId });\n }\n}\n","import type { Crm, TypeSummary } from \"@odla-ai/crm\";\nimport type { ChapterDb } from \"./types\";\n\n/** The contact data the hub shares for a prospect. `hubRecordId` is the stable\n * idempotency key (the hub's crm_record id). */\nexport interface SharedPerson {\n email: string;\n name?: string;\n firstName?: string;\n lastName?: string;\n phone?: string;\n linkedin?: string;\n hubRecordId: string;\n}\n\n/** Convenience wire shape for sharing the default `company` CRM type. */\nexport interface SharedBusiness {\n type: \"company\";\n name: string;\n domain?: string;\n industry?: string;\n location?: string;\n linkedin?: string;\n notes?: string;\n hubRecordId: string;\n}\n\n/** Versioned generic wire shape. `input` is validated against the follower's\n * own CRM type before any write, so a leader cannot smuggle undeclared fields. */\nexport interface SharedRecordV1 {\n version: 1;\n type: string;\n hubRecordId: string;\n input: Record<string, unknown>;\n}\n\n/** Current wire envelope. `source.siteId` prevents records from two leaders\n * with the same local id from colliding in a follower CRM. */\nexport interface SharedRecordV2 {\n version: 2;\n source: { siteId: string; recordId: string };\n type: string;\n input: Record<string, unknown>;\n}\n\n/** Accepted generic share envelopes. Version 1 remains readable for migration. */\nexport type SharedRecord = SharedRecordV1 | SharedRecordV2;\n\n/** Privacy-bounded follower status returned to an authenticated leader. */\nexport interface NetworkSnapshot {\n version: 1;\n site: { id: string; name: string; mode: string };\n generatedAt: number;\n types: TypeSummary[];\n}\n\n/** One configured target's latest live result in a leader rollup. */\nexport interface NetworkRollupTarget {\n id: string;\n name: string;\n url: string;\n available: boolean;\n generatedAt?: number;\n types?: TypeSummary[];\n error?: string;\n}\n\n/** Cross-target totals returned to the local leader admin. */\nexport interface NetworkRollup {\n configured: number;\n available: number;\n totalRecords: number;\n types: Array<{ type: string; total: number; stages: Record<string, number> }>;\n targets: NetworkRollupTarget[];\n}\n\n/** Privacy-bounded CRM record returned by a follower to one configured,\n * authenticated reader. */\nexport interface NetworkRecord {\n id: string;\n type: string;\n name: string;\n stage?: string;\n fields: Record<string, unknown>;\n createdAt: number;\n updatedAt: number;\n}\n\n/** One bounded, offset-paged follower record window. */\nexport interface NetworkRecordPage {\n version: 1;\n site: { id: string; name: string };\n type: string;\n records: NetworkRecord[];\n total: number;\n limit: number;\n offset: number;\n}\n\n/** Leader-private note attached to a stable remote record identity. */\nexport interface NetworkRecordNote {\n id: string;\n targetId: string;\n recordType: string;\n recordId: string;\n body: string;\n authorId: string;\n authorEmail?: string;\n createdAt: number;\n}\n\n/** A note deliberately shared across the federation edge and stored in the\n * follower CRM activity feed. Unlike NetworkRecordNote, this is visible to\n * the follower's own CRM admins. */\nexport interface NetworkSharedNote {\n id: string;\n sourceId: string;\n recordType: string;\n recordId: string;\n body: string;\n createdAt: number;\n}\n\nexport interface NormalizedSharedRecord {\n version: 1 | 2;\n sourceId: string;\n sourceRecordId: string;\n type: string;\n input: Record<string, unknown>;\n}\n\n/** Dependencies for applying a shared projection. */\nexport interface ProjectionDeps {\n crm: Crm;\n db: ChapterDb;\n now: () => number;\n newId: () => string;\n}\n\n/** Safe defaults when a target does not declare an explicit field allowlist. */\nexport const DEFAULT_SHARE_FIELDS: Readonly<Record<string, readonly string[]>> = {\n person: [\"name\", \"email\", \"firstName\", \"lastName\", \"phone\", \"linkedin\"],\n company: [\"name\", \"domain\", \"industry\", \"location\", \"linkedin\", \"notes\"],\n};\n","// The OPERATIONAL slice of the one-way person projection: applications + $users\n// -> crm_record, mirroring pipeline stage, a billing snapshot, and the Clerk\n// identity link. `network.ts` projects identity/contact on submit; this adds the\n// operational state the admin surface and the hub read from, so the pipeline\n// stays authoritative in `applications.status` while the CRM carries one\n// relationship surface over the person. Fired AFTER the authoritative write and\n// wrapped in `.catch` at every call site: a CRM hiccup never 5xxs a lifecycle op.\n//\n// Idempotent by construction — every sync resolves the person by lowercased\n// primary email first, so re-running (including the backfill route) updates in\n// place. Generalized from the reference site: the field set is the site's\n// configured `crmFields`, not a hardcoded list.\nimport { createRecord, updateRecord, setStage, linkIdentity } from \"@odla-ai/crm\";\nimport { sharedPersonInput } from \"./network\";\nimport type { ProjectionDeps } from \"./network\";\nimport type { Chapter, ChapterDb } from \"./types\";\n\nconst str = (v: unknown): string => (typeof v === \"string\" ? v : v == null ? \"\" : String(v));\n\n/** Build the projection deps from a worker request's db + context.\n *\n * Shared so every route that writes `applications.status` mirrors it the same\n * way. Status is written from four places (admin approve, admin PATCH, the\n * Stripe webhook, and booking) and the admin dashboard reads its pipeline from\n * `crm_record.stage`, so a route that skips the mirror silently reports the\n * wrong funnel. */\nexport const crmDeps = (\n db: ChapterDb,\n ctx: { chapter: Chapter },\n): ProjectionDeps & { chapter: Chapter } => ({\n crm: ctx.chapter.crm,\n db,\n now: () => Date.now(),\n newId: () => crypto.randomUUID(),\n chapter: ctx.chapter,\n});\n\n/** The crm `person` input for one application row: the built-in identity/contact\n * fields plus each configured `crmFields` value present on the row. */\nexport function personInputFromApp(chapter: Chapter, app: Record<string, unknown>): Record<string, unknown> {\n const input = sharedPersonInput({\n email: str(app.email),\n firstName: str(app.firstName) || undefined,\n lastName: str(app.lastName) || undefined,\n phone: str(app.phone) || undefined,\n linkedin: str(app.linkedin) || undefined,\n hubRecordId: str(app.id),\n });\n for (const f of chapter.application.crmFields) {\n if (app[f] !== undefined) input[f] = app[f];\n }\n if (app.id !== undefined) input.applicationId = str(app.id);\n return input;\n}\n\n// Promoted billing-facet columns derived from the application's Stripe fields +\n// status. Written directly (not through createRecord/updateRecord, which never\n// touch promoted columns), so they never clobber the person input.\nfunction billingColumns(app: Record<string, unknown>): Record<string, unknown> {\n const status = str(app.status);\n const paid = Boolean(app.stripeSubscriptionId) && status !== \"refunded\";\n const billingStatus = status === \"refunded\" ? \"refunded\" : app.canceled === true ? \"canceled\" : paid ? \"active\" : \"none\";\n const cols: Record<string, unknown> = { billingStatus };\n if (app.stripeCustomerId) cols.stripeCustomerId = str(app.stripeCustomerId);\n if (app.stripeSubscriptionId) cols.subscriptionId = str(app.stripeSubscriptionId);\n if (typeof app.renewalAt === \"number\") cols.renewalAt = app.renewalAt;\n return cols;\n}\n\n/** Upsert the person record for one application (or a synthetic `{ email,\n * firstName }` account row) and mirror its stage, billing snapshot, and Clerk\n * identity. `stage` is the `applications.status` to mirror — omit for\n * account-only rows not in the pipeline. Throws on failure (the backfill route\n * counts; the operational call sites wrap in `.catch`). */\nexport async function syncApplicationToCrm(\n deps: ProjectionDeps & { chapter: Chapter },\n opts: { app: Record<string, unknown>; stage?: string },\n): Promise<string | null> {\n const emailKey = str(opts.app.email).toLowerCase();\n if (!emailKey) return null;\n // The narrower shape the crm record helpers take (no chapter).\n const recordDeps = { crm: deps.crm, db: deps.db as never, now: deps.now, newId: deps.newId };\n const input = personInputFromApp(deps.chapter, opts.app);\n\n const { crm_record } = await deps.db.query({\n crm_record: { $: { where: { type: \"person\", primaryEmail: emailKey }, limit: 1 } },\n });\n const existing = crm_record?.[0] ?? null;\n const stage = opts.stage || undefined;\n\n let recordId: string;\n if (existing && typeof existing.id === \"string\") {\n recordId = existing.id;\n await updateRecord(recordDeps, { id: recordId, input });\n } else {\n const created = await createRecord(recordDeps, { type: \"person\", input, ...(stage ? { stage } : {}) });\n recordId = created.id;\n }\n\n // Stage mirror: move only on an actual change, under a stable mutationId so a\n // replay never piles up duplicate stage_change activities. Best-effort — a\n // stage not on the crm person type must not fail the whole sync.\n if (existing && stage && existing.stage !== stage) {\n await setStage(recordDeps, { id: recordId, to: stage, authorId: \"system\", mutationId: `crm:stage:${recordId}:${stage}` }).catch(() => undefined);\n }\n\n await deps.db.transact([{ t: \"update\", ns: \"crm_record\", id: recordId, attrs: billingColumns(opts.app) }]);\n\n // Identity link: stamps clerkUserId when a $users row matches the email; a\n // no-op until the person has an account. Best-effort — a just-created record\n // can briefly lag the read, and the link retries on the next sync.\n await linkIdentity(recordDeps, { recordId, email: emailKey, mutationId: `crm:link:${recordId}:${emailKey}` }).catch(() => undefined);\n\n return recordId;\n}\n\n/** Backfill / repair: project every application (newest per person) and every\n * account-only `$users` row into the CRM. Idempotent (safe to re-run). Dev\n * volumes fit one 1000-row page. Returns `{ synced, errors }`. */\nexport async function backfillCrm(deps: ProjectionDeps & { chapter: Chapter }): Promise<{ synced: number; errors: Array<{ email: string; error: string }> }> {\n const data = await deps.db.query({\n applications: { $: { order: { createdAt: \"desc\" }, limit: 1000 } },\n $users: { $: { limit: 1000 } },\n });\n const seen = new Set<string>();\n let synced = 0;\n const errors: Array<{ email: string; error: string }> = [];\n\n const run = async (app: Record<string, unknown>, stage?: string): Promise<void> => {\n const key = str(app.email).toLowerCase();\n if (!key || seen.has(key)) return; // newest-first: one record per person\n seen.add(key);\n try {\n await syncApplicationToCrm(deps, { app, stage });\n synced += 1;\n } catch (err) {\n errors.push({ email: key, error: err instanceof Error ? err.message : String(err) });\n }\n };\n\n for (const a of (data.applications ?? []) as Array<Record<string, unknown>>) await run(a, str(a.status));\n for (const u of (data.$users ?? []) as Array<Record<string, unknown>>) {\n if (u.deleted === true) continue;\n await run({ email: u.email, firstName: str(u.name) });\n }\n return { synced, errors };\n}\n","// Pure aggregation helpers for the admin dashboard: a weekly time-series bucketer\n// and the annualized-run-rate math for a Stripe subscription. Kept out of the\n// route so both dashboard and billing share one definition and it is unit-tested\n// without a network call.\n\n/** Bucket `{ t, v }` points into the last `weeks` weekly buckets ending at `now`\n * (epoch ms), summing `v` per bucket. Returns oldest→newest `{ weekStart, value\n * }`, so a caller renders a sparkline directly. Points outside the window are\n * ignored. */\nexport function bucketSeries(\n points: Array<{ t: number; v: number }>,\n now: number,\n weeks = 12,\n): Array<{ weekStart: number; value: number }> {\n const WEEK = 7 * 86_400_000;\n const end = now;\n const start = end - weeks * WEEK;\n const buckets = Array.from({ length: weeks }, (_, i) => ({ weekStart: start + i * WEEK, value: 0 }));\n for (const p of points) {\n if (!Number.isFinite(p.t) || p.t < start || p.t > end) continue;\n const idx = Math.min(weeks - 1, Math.floor((p.t - start) / WEEK));\n const bucket = buckets[idx];\n if (bucket) bucket.value += Number.isFinite(p.v) ? p.v : 0;\n }\n return buckets;\n}\n\n/** Labels and current/previous values for one dashboard comparison window. */\nexport interface DashboardMetricSeries {\n labels: string[];\n current: number[];\n previous: number[];\n}\n\n/** Week-over-week and month-over-month series consumed by MetricWidget. */\nexport interface DashboardMetricData {\n wow: DashboardMetricSeries;\n mom: DashboardMetricSeries;\n}\n\nfunction periodSeries(\n points: Array<{ t: number; v: number }>,\n now: number,\n count: number,\n periodMs: number,\n): DashboardMetricSeries {\n const start = now - count * periodMs;\n const previousStart = start - count * periodMs;\n const current = Array.from({ length: count }, () => 0);\n const previous = Array.from({ length: count }, () => 0);\n for (const point of points) {\n if (!Number.isFinite(point.t) || !Number.isFinite(point.v)) continue;\n if (point.t >= start && point.t <= now) {\n const index = Math.min(count - 1, Math.floor((point.t - start) / periodMs));\n current[index] = (current[index] ?? 0) + point.v;\n } else if (point.t >= previousStart && point.t < start) {\n const index = Math.min(count - 1, Math.floor((point.t - previousStart) / periodMs));\n previous[index] = (previous[index] ?? 0) + point.v;\n }\n }\n const labels = current.map((_, index) =>\n new Date(start + index * periodMs).toISOString().slice(5, 10));\n return { labels, current, previous };\n}\n\n/** MetricWidget-ready daily and weekly comparison windows. */\nexport function dashboardMetricData(\n points: Array<{ t: number; v: number }>,\n now: number,\n): DashboardMetricData {\n const DAY = 86_400_000;\n return {\n wow: periodSeries(points, now, 7, DAY),\n mom: periodSeries(points, now, 4, 7 * DAY),\n };\n}\n\n/** Annualized cents for a Stripe subscription: sum each item's\n * `unit_amount * quantity`, ×12 for monthly intervals. A yearly interval is\n * taken as-is. Returns 0 for a shape with no priced items. */\nexport function subAnnualCents(sub: Record<string, unknown>): number {\n const items = ((sub.items as { data?: Array<Record<string, unknown>> } | undefined)?.data ?? []);\n let cents = 0;\n for (const it of items) {\n const price = (it.price ?? {}) as { unit_amount?: number; recurring?: { interval?: string } };\n const per = (price.unit_amount ?? 0) * ((it.quantity as number) ?? 1);\n cents += price.recurring?.interval === \"month\" ? per * 12 : per;\n }\n return cents;\n}\n","// The Stripe payments provider — the only I/O half of payments. Talks to the\n// Stripe REST API over @odla-ai/stripe's fetch transport, and maps 1:1 onto the\n// membership-specific event normalization in ./payments. The worker\n// resolves secrets from the vault per request and constructs this; the routes own\n// every db write so idempotency stays at the db layer.\nimport { stripeRequest, verifyStripeSignature, type StripeRequestResult } from \"@odla-ai/stripe\";\nimport { normalizeWebhookEvent } from \"./payments\";\nimport type { StripeEvent, WebhookEvent } from \"./payments\";\n\n/** Inputs to create an application's founding-member subscription. */\nexport interface CreateSubscriptionInput {\n appId: string;\n environment: string;\n applicationId: string;\n groupId: string;\n email: string;\n name: string;\n priceId: string;\n existingCustomerId?: string;\n}\n\n/** The client secret to confirm card entry, plus the ids to persist. */\nexport interface CreateSubscriptionResult {\n customerId: string;\n subscriptionId: string;\n clientSecret: string;\n}\n\n/** The outcome of a full refund. */\nexport interface RefundResult {\n refundedCents: number | null;\n subscriptionCanceled: boolean;\n}\n\n/** The capabilities the payment routes depend on — Stripe is one impl. */\nexport interface PaymentsProvider {\n createSubscription(input: CreateSubscriptionInput): Promise<CreateSubscriptionResult>;\n ingestWebhook(\n rawBody: string,\n sigHeader: string,\n ): Promise<{ ok: true; eventId: string; event: WebhookEvent } | { ok: false; reason: \"bad_signature\" }>;\n refund(input: { customerId: string; subscriptionId: string }): Promise<RefundResult>;\n}\n\n/** The result of a Stripe Backend API call: ok + status + parsed JSON body. */\nexport type StripeResult = StripeRequestResult<Record<string, unknown>>;\n\n/** Call the Stripe Backend API (form-encoded, Bearer sk_). Exposed so the admin\n * billing/dashboard reads and the refund route share one Stripe client instead\n * of each re-deriving the auth + encoding. */\nexport async function stripeCall(\n sk: string,\n method: \"GET\" | \"POST\" | \"DELETE\",\n path: string,\n params?: Record<string, unknown>,\n idempotencyKey?: string,\n): Promise<StripeResult> {\n return stripeRequest(\n { secretKey: sk },\n method,\n path,\n params,\n idempotencyKey ? { idempotencyKey } : {},\n );\n}\n\nfunction fail(op: string, r: StripeResult): never {\n const err = new Error(`stripe ${op} failed: ${r.status}`) as Error & { code: string };\n err.code = \"stripe_error\";\n throw err;\n}\n\nfunction clientSecretOf(sub: Record<string, unknown>): string | undefined {\n const inv = sub.latest_invoice as Record<string, unknown> | undefined;\n const confirmation = inv?.confirmation_secret as Record<string, unknown> | undefined;\n const intent = inv?.payment_intent as Record<string, unknown> | undefined;\n const secret = confirmation?.client_secret ?? intent?.client_secret;\n return typeof secret === \"string\" ? secret : undefined;\n}\n\nfunction requireSecret(secretKey: string | undefined): string {\n if (!secretKey) {\n const err = new Error(\"stripe secret key missing\") as Error & { code: string };\n err.code = \"not_configured\";\n throw err;\n }\n return secretKey;\n}\n\n/** Build the Stripe provider. `secretKey` powers charging/refunds; `webhookSecret`\n * powers webhook ingest. Each is resolved from the vault per request, so the\n * webhook route can construct an ingest-only provider without the secret key. */\nexport function createStripeProvider(config: { secretKey?: string; webhookSecret?: string }): PaymentsProvider {\n const { secretKey, webhookSecret } = config;\n return {\n async createSubscription(input) {\n const sk = requireSecret(secretKey);\n const meta = {\n applicationId: input.applicationId,\n groupId: input.groupId,\n email: input.email,\n odlaAppId: input.appId,\n odlaEnvironment: input.environment,\n };\n let customerId = input.existingCustomerId;\n if (!customerId) {\n const cust = await stripeCall(\n sk,\n \"POST\",\n \"/v1/customers\",\n { email: input.email, name: input.name, metadata: meta },\n `cus:${input.applicationId}`,\n );\n if (!cust.ok) fail(\"customer create\", cust);\n customerId = String(cust.body.id);\n }\n const sub = await stripeCall(\n sk,\n \"POST\",\n \"/v1/subscriptions\",\n {\n customer: customerId,\n \"items[0][price]\": input.priceId,\n payment_behavior: \"default_incomplete\",\n \"payment_settings[save_default_payment_method]\": \"on_subscription\",\n \"payment_settings[payment_method_types][0]\": \"card\",\n \"expand[0]\": \"latest_invoice.confirmation_secret\",\n metadata: meta,\n },\n // Hardening: one subscription per application, so a client\n // retry between create and the db write can't orphan a second one.\n `sub:${input.applicationId}`,\n );\n if (!sub.ok) fail(\"subscription create\", sub);\n const clientSecret = clientSecretOf(sub.body);\n if (!clientSecret) fail(\"subscription confirmation-secret missing\", sub);\n return { customerId, subscriptionId: String(sub.body.id), clientSecret };\n },\n\n async ingestWebhook(rawBody, sigHeader) {\n if (!webhookSecret || !(await verifyStripeSignature(rawBody, sigHeader, webhookSecret))) {\n return { ok: false, reason: \"bad_signature\" };\n }\n const event = JSON.parse(rawBody) as StripeEvent;\n return { ok: true, eventId: event.id, event: normalizeWebhookEvent(event) };\n },\n\n async refund(input) {\n const sk = requireSecret(secretKey);\n const charges = await stripeCall(sk, \"GET\", \"/v1/charges\", { customer: input.customerId, limit: 100 });\n if (!charges.ok) fail(\"charges list\", charges);\n const rows = (charges.body.data as Array<Record<string, unknown>> | undefined) ?? [];\n const paid = rows.filter((c) => c.status === \"succeeded\" && c.refunded !== true);\n const charge = paid[paid.length - 1]; // Stripe returns newest-first; refund the earliest.\n if (!charge) {\n const err = new Error(\"no paid charge to refund\") as Error & { code: string };\n err.code = \"no_charge\";\n throw err;\n }\n const refund = await stripeCall(sk, \"POST\", \"/v1/refunds\", { charge: String(charge.id) });\n if (!refund.ok) fail(\"refund\", refund);\n const cancel = await stripeCall(sk, \"DELETE\", `/v1/subscriptions/${input.subscriptionId}`);\n const amount = refund.body.amount;\n return { refundedCents: typeof amount === \"number\" ? amount : null, subscriptionCanceled: cancel.ok };\n },\n };\n}\n","// Apply-time account provisioning. When an application arrives, the worker mints\n// a Clerk invitation so the applicant gets a path into their member area — the\n// generalized server-side account step. Chapter calls the Clerk\n// Backend API directly over fetch (vault clerk_secret_key), mirroring\n// @odla-ai/auth-clerk's createInvitation but self-contained, so it never pulls the\n// auth-clerk UI package into the worker bundle. Best-effort at the call site: a\n// provisioning failure never fails the application.\n\n/** The outcome of a Clerk provisioning call. `existed` marks the heal case: Clerk\n * rejected it because the account/invitation is already there, which is the end\n * state we wanted anyway. */\nexport interface ClerkResult {\n ok: boolean;\n status: number;\n existed?: boolean;\n /** Set when an `existed` heal also refreshed the account's metadata. */\n refreshed?: boolean;\n}\n\n// Clerk answers 422 when the email already has a user (or a pending invitation).\n// For apply-time provisioning that's success, not failure — the account exists.\nconst heal = (status: number): ClerkResult =>\n status === 422 ? { ok: true, status, existed: true } : { ok: false, status };\n\n/** Inputs for a Clerk invitation. */\nexport interface ClerkInviteInput {\n email: string;\n /** Where the accept-invitation link lands (usually the member area). */\n redirectUrl?: string;\n /** Written to the invitation's `public_metadata`. Clerk application\n * invitations cannot carry private metadata, so never put applicant profile\n * fields here. Chapter completes that backend-only write after acceptance. */\n publicMetadata?: Record<string, unknown>;\n}\n\n/** Build the Clerk Backend API invitation request (path + JSON body). Pure, so\n * the wire shape is testable without a network call. */\nexport function clerkInviteRequest(input: ClerkInviteInput): { path: string; body: Record<string, unknown> } {\n return {\n path: \"/v1/invitations\",\n body: {\n email_address: input.email,\n notify: true,\n ...(input.redirectUrl ? { redirect_url: input.redirectUrl } : {}),\n ...(input.publicMetadata ? { public_metadata: input.publicMetadata } : {}),\n },\n };\n}\n\n/** POST the invitation to the Clerk Backend API. A repeat invite for an\n * already-invited email heals to `{ ok: true, existed: true }` rather than\n * reporting a failure the caller would have to special-case. */\nexport async function createClerkInvitation(\n secretKey: string,\n input: ClerkInviteInput,\n fetchImpl: typeof fetch = fetch,\n): Promise<ClerkResult> {\n const { path, body } = clerkInviteRequest(input);\n const res = await fetchImpl(`https://api.clerk.com${path}`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${secretKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n return res.ok ? { ok: true, status: res.status } : heal(res.status);\n}\n\n/** Inputs for a server-side Clerk user create. */\nexport interface ClerkUserInput {\n email: string;\n firstName?: string;\n lastName?: string;\n /** Backend-authored, browser-readable claims such as `role`. */\n publicMetadata?: Record<string, unknown>;\n /** Backend-only account signals and profile data. */\n privateMetadata?: Record<string, unknown>;\n /** Optional metadata merge used only when create returns 422 for an existing\n * account. This lets migrations remove legacy keys without putting tombstone\n * values on a newly-created user. Defaults to the create metadata. */\n repairMetadata?: ClerkMetadataInput;\n}\n\n/** Build the Clerk Backend API user-create request. The account is created\n * passwordless (the member signs in via the site's Clerk flow), so join step 3\n * can say the account is ready — the \"create\" alternative to an invitation. */\nexport function clerkUserRequest(input: ClerkUserInput): { path: string; body: Record<string, unknown> } {\n return {\n path: \"/v1/users\",\n body: {\n email_address: [input.email],\n skip_password_requirement: true,\n ...(input.firstName ? { first_name: input.firstName } : {}),\n ...(input.lastName ? { last_name: input.lastName } : {}),\n ...(input.publicMetadata !== undefined ? { public_metadata: input.publicMetadata } : {}),\n ...(input.privateMetadata !== undefined ? { private_metadata: input.privateMetadata } : {}),\n },\n };\n}\n\n/** One merge-PATCH to the metadata fields Clerk exposes on its Backend API. */\nexport interface ClerkMetadataInput {\n publicMetadata?: Record<string, unknown>;\n privateMetadata?: Record<string, unknown>;\n}\n\n/** Merge metadata into an existing Clerk user. Nested `null` values remove old\n * keys, which Chapter uses to migrate its former public profile into private\n * metadata without disturbing the public `role` claim. */\nexport async function updateClerkUserMetadata(\n secretKey: string,\n userId: string,\n input: ClerkMetadataInput,\n fetchImpl: typeof fetch = fetch,\n): Promise<boolean> {\n const res = await fetchImpl(`https://api.clerk.com/v1/users/${encodeURIComponent(userId)}/metadata`, {\n method: \"PATCH\",\n headers: { authorization: `Bearer ${secretKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({\n ...(input.publicMetadata !== undefined ? { public_metadata: input.publicMetadata } : {}),\n ...(input.privateMetadata !== undefined ? { private_metadata: input.privateMetadata } : {}),\n }),\n });\n return res.ok;\n}\n\n/** Look a Clerk account up by email and merge its metadata.\n *\n * Returns `false` when no matching user can be resolved or Clerk rejects the\n * lookup or update. Chapter uses this for create-healing and invitation\n * adoption so a repeated application repairs the private account snapshot.\n */\nexport async function updateClerkUserMetadataByEmail(\n secretKey: string,\n email: string,\n input: ClerkMetadataInput,\n fetchImpl: typeof fetch = fetch,\n): Promise<boolean> {\n const auth = { authorization: `Bearer ${secretKey}` };\n const found = await fetchImpl(`https://api.clerk.com/v1/users?email_address=${encodeURIComponent(email)}&limit=1`, { headers: auth });\n if (!found.ok) return false;\n const users = (await found.json().catch(() => null)) as Array<{ id?: unknown }> | null;\n const id = Array.isArray(users) && typeof users[0]?.id === \"string\" ? users[0].id : undefined;\n if (!id) return false;\n return updateClerkUserMetadata(secretKey, id, input, fetchImpl);\n}\n\n/** Create the applicant's Clerk account server-side. A repeat for an email that\n * already has an account heals to `{ ok: true, existed: true }` — the account\n * exists, which is the state apply-time provisioning wanted — and refreshes\n * supplied public/private metadata on the existing account so a re-application\n * repairs a previously missed create (`refreshed: true`). */\nexport async function createClerkUser(\n secretKey: string,\n input: ClerkUserInput,\n fetchImpl: typeof fetch = fetch,\n): Promise<ClerkResult> {\n const { path, body } = clerkUserRequest(input);\n const res = await fetchImpl(`https://api.clerk.com${path}`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${secretKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (res.ok) return { ok: true, status: res.status };\n const healed = heal(res.status);\n const repair = input.repairMetadata ?? {\n ...(input.publicMetadata !== undefined ? { publicMetadata: input.publicMetadata } : {}),\n ...(input.privateMetadata !== undefined ? { privateMetadata: input.privateMetadata } : {}),\n };\n if (\n !healed.existed ||\n (repair.publicMetadata === undefined && repair.privateMetadata === undefined)\n ) return healed;\n const refreshed = await updateClerkUserMetadataByEmail(secretKey, input.email, {\n ...(repair.publicMetadata !== undefined ? { publicMetadata: repair.publicMetadata } : {}),\n ...(repair.privateMetadata !== undefined ? { privateMetadata: repair.privateMetadata } : {}),\n }, fetchImpl).catch(() => false);\n return { ...healed, refreshed };\n}\n","// The odla->Clerk write half: server-side Clerk role read/list/write, the gap\n// beside clerk.ts's create/invite/heal. Roles live in `public_metadata.role`; an\n// absent role means the lowest rung (\"provisional\") — chapter never writes it at\n// create. Account profile signals live in backend-only `private_metadata`; the\n// role write is a MERGE-PATCH of only `{ role }`, so it cannot clobber them.\n// Chapter calls the Clerk Backend API over fetch with the vault\n// `clerk_secret_key`.\n\nconst CLERK_API = \"https://api.clerk.com\";\nconst DEFAULT_ROLE = \"provisional\";\nconst PAGE = 100;\n\n/** A Clerk user as chapter's role layer sees it. `role` defaults to the lowest\n * rung when `public_metadata` carries none. Raw public/private metadata is\n * returned only from this backend helper; `profile` and `applicationId` are the\n * normalized Chapter-owned private signals. */\nexport interface ClerkUserRecord {\n id: string;\n email?: string;\n role: string;\n publicMetadata: Record<string, unknown>;\n privateMetadata: Record<string, unknown>;\n profile: Record<string, unknown>;\n applicationId?: string;\n}\n\n// The Clerk Backend API user object — only the fields chapter reads.\ninterface ClerkApiUser {\n id?: unknown;\n email_addresses?: Array<{ email_address?: unknown }>;\n public_metadata?: Record<string, unknown>;\n private_metadata?: Record<string, unknown>;\n}\n\nfunction toRecord(u: ClerkApiUser): ClerkUserRecord | null {\n if (typeof u.id !== \"string\") return null;\n const pm = (u.public_metadata ?? {}) as Record<string, unknown>;\n const privateMetadata = (u.private_metadata ?? {}) as Record<string, unknown>;\n const rawProfile = privateMetadata.profile;\n const profile = rawProfile && typeof rawProfile === \"object\" && !Array.isArray(rawProfile)\n ? rawProfile as Record<string, unknown>\n : {};\n const applicationId = typeof privateMetadata.applicationId === \"string\"\n ? privateMetadata.applicationId\n : undefined;\n const role = typeof pm.role === \"string\" && pm.role ? pm.role : DEFAULT_ROLE;\n const email = u.email_addresses?.[0]?.email_address;\n return {\n id: u.id,\n email: typeof email === \"string\" ? email : undefined,\n role,\n publicMetadata: pm,\n privateMetadata,\n profile,\n ...(applicationId ? { applicationId } : {}),\n };\n}\n\nasync function clerkGet(path: string, secretKey: string, fetchImpl: typeof fetch): Promise<unknown> {\n const res = await fetchImpl(`${CLERK_API}${path}`, { headers: { authorization: `Bearer ${secretKey}` } });\n if (!res.ok) throw new Error(`clerk GET ${path} → ${res.status}`);\n return res.json();\n}\n\n/** Look a Clerk user up by email. `null` when no such user — or when the lookup\n * fails (a role gate treats an unresolvable user as absent, matching the site's\n * own fallback). Role defaults to provisional when unset. */\nexport async function clerkGetUserByEmail(secretKey: string, email: string, fetchImpl: typeof fetch = fetch): Promise<ClerkUserRecord | null> {\n const data = await clerkGet(`/v1/users?email_address=${encodeURIComponent(email)}&limit=1`, secretKey, fetchImpl).catch(() => null);\n const user = Array.isArray(data) ? (data[0] as ClerkApiUser | undefined) : undefined;\n return user ? toRecord(user) : null;\n}\n\n/** Fetch a Clerk user by id, for role-change gating. `null` when missing or on a\n * failed lookup. Role defaults to provisional when unset. */\nexport async function clerkGetUser(secretKey: string, id: string, fetchImpl: typeof fetch = fetch): Promise<ClerkUserRecord | null> {\n const data = await clerkGet(`/v1/users/${encodeURIComponent(id)}`, secretKey, fetchImpl).catch(() => null);\n return data ? toRecord(data as ClerkApiUser) : null;\n}\n\n/** List ALL Clerk users with their roles, auto-paginating. A membership community\n * outgrows one page, and a fixed `limit=100` would silently drop members from the\n * admin roster with no error — so this pages (offset in steps of {@link PAGE})\n * until a short page. A page fetch that fails THROWS rather than returning a\n * partial list, so the caller never mistakes a truncated roster for the whole. */\nexport async function clerkListUsers(secretKey: string, fetchImpl: typeof fetch = fetch): Promise<ClerkUserRecord[]> {\n const out: ClerkUserRecord[] = [];\n for (let offset = 0; ; offset += PAGE) {\n const data = await clerkGet(`/v1/users?limit=${PAGE}&offset=${offset}`, secretKey, fetchImpl);\n const page = Array.isArray(data) ? (data as ClerkApiUser[]) : [];\n for (const u of page) {\n const record = toRecord(u);\n if (record) out.push(record);\n }\n if (page.length < PAGE) break;\n }\n return out;\n}\n\n/** Write a user's role: a MERGE-PATCH of only `{ role }` on `public_metadata`.\n * The backend-only profile lives in `private_metadata`, so the two signals\n * cannot overwrite each other. Returns whether the role write stuck. */\nexport async function clerkSetRole(secretKey: string, id: string, role: string, fetchImpl: typeof fetch = fetch): Promise<boolean> {\n const res = await fetchImpl(`${CLERK_API}/v1/users/${encodeURIComponent(id)}/metadata`, {\n method: \"PATCH\",\n headers: { authorization: `Bearer ${secretKey}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({ public_metadata: { role } }),\n });\n return res.ok;\n}\n","// The Clerk capability descriptor: documentation-as-data — \"what settings/secrets\n// does turning Clerk on need?\", \"what must the CLI provision?\", and \"what data\n// syncs, in which direction?\". It lives here (not in the browser package\n// @odla-ai/auth-clerk) because the sync contract is implemented by odla-db + the\n// platform webhook (provider->odla) and by chapter's clerk.ts (odla->provider),\n// neither of which is browser code. auth-clerk stays a pure UI package. Data only:\n// it describes the capability, it performs none of it.\n\n/** Which auth mode a secret is required for: `\"client\"` (publishable key only) or\n * `\"full\"` (server-side profile/role reads + writes, needing the vault secret). */\nexport type SecretMode = \"client\" | \"full\";\n\n/** A configuration value the capability needs (e.g. the publishable key). */\nexport interface IntegrationSetting {\n key: string;\n description: string;\n /** Safe to ship to the browser? (publishable keys are; secrets are not). */\n public: boolean;\n /** Expected value shape, e.g. a \"pk_\" prefix. */\n pattern?: string;\n /** Stored per environment (dev/prod)? */\n perEnv: boolean;\n /** Where the value is stored and read from. */\n source: string;\n}\n\n/**\n * A secret the capability needs, held in the tenant vault.\n *\n * Structurally the odla CLI's `IntegrationSecret`: `name` is the vault name\n * byte-for-byte, so `odla-ai doctor`, `odla-ai secrets status`, and the\n * repo's `check:secrets` gate can hold this declaration against the name the\n * platform actually reads. `mode` is chapter's own addition and the CLI\n * ignores it.\n */\nexport interface IntegrationSecret {\n /** Vault name, exactly as `odla-ai secrets set <name>` writes it. */\n name: string;\n description: string;\n pattern?: string;\n /** Auth mode that requires this secret (\"full\" pulls user profiles). */\n mode: SecretMode;\n /** Whether the capability is broken without it. Both Clerk secrets are\n * needed only by auth mode \"full\", so both are optional. */\n required?: boolean;\n}\n\n/** One data-sync contract. A capability may declare several (e.g. an inbound\n * webhook mirror AND an outbound write), so {@link IntegrationDescriptor.syncs}\n * is a list. The mechanism is declared, not reimplemented here. */\nexport interface IntegrationSync {\n engine: string;\n direction: \"provider->odla\" | \"odla->provider\" | \"bidirectional\";\n entity: string;\n fields: string[];\n webhook?: string;\n onDelete?: string;\n}\n\n/** The provisioning split: human, CLI, and doctor-assertable steps. */\nexport interface IntegrationProvision {\n /** Steps a human performs (out-of-band, e.g. in the Clerk dashboard). */\n human: string[];\n /** Steps the odla CLI automates. */\n cli: string[];\n /** Checks `odla doctor` should assert. */\n doctor: string[];\n}\n\n/** Documentation-as-data for a provider capability, consumed by the odla CLI,\n * `odla doctor`, and the docs. */\nexport interface IntegrationDescriptor {\n id: string;\n title: string;\n npm: string;\n settings: IntegrationSetting[];\n secrets: IntegrationSecret[];\n /** Every data-sync contract the capability declares, each with its direction. */\n syncs: IntegrationSync[];\n provision: IntegrationProvision;\n}\n\n/**\n * The concrete {@link IntegrationDescriptor} for the Clerk capability. Declares\n * the one public `setting` (the `pk_*` publishable key, served to the SPA), the\n * `secrets` auth mode `\"full\"` needs in the tenant vault, BOTH sync directions —\n * the inbound `$users` webhook mirror (`provider->odla`) and the outbound\n * public role/private profile write via `clerk_secret_key` (`odla->provider`,\n * chapter's `clerk.ts`) — and the `provision` split. Data only; it performs\n * none of it.\n */\nexport const clerkIntegration: IntegrationDescriptor = {\n id: \"clerk\",\n title: \"Clerk end-user auth\",\n npm: \"@odla-ai/chapter\",\n settings: [\n {\n key: \"publishableKey\",\n description: \"Clerk publishable key (pk_*). Public by design; served to the SPA (loads clerk-js from Clerk's CDN via @odla-ai/auth-clerk).\",\n public: true,\n pattern: \"pk_\",\n perEnv: true,\n source: \"apps-registry auth[env].publishableKey (from odla.config.mjs auth.clerk.<env>)\",\n },\n ],\n secrets: [\n {\n // odla-db reads this exact name (CLERK_WEBHOOK_SECRET_NAME in the\n // platform's clerk-webhook.ts); it is also what `odla-ai secrets set`\n // writes. It read \"CLERK_WEBHOOK_SECRET\" until 0.30.0, which sent\n // adopters to store the value under a name nothing looks up.\n name: \"clerk_webhook_secret\",\n description: \"Svix signing secret for Clerk user webhooks — verifies $users sync events.\",\n pattern: \"whsec_\",\n mode: \"full\",\n required: false,\n },\n {\n name: \"clerk_secret_key\",\n description: \"Clerk backend key (sk_*) — powers account creation, the public role claim, and backend-only private profile signals; it also lets odla-db resolve user email/name via the Clerk API.\",\n pattern: \"sk_\",\n mode: \"full\",\n required: false,\n },\n ],\n syncs: [\n {\n engine: \"@odla-ai/db $users (Clerk webhook -> tenant graph)\",\n direction: \"provider->odla\",\n entity: \"$users\",\n // Matches the webhook mapper: the mirror carries id + primary email + name + avatar.\n fields: [\"id\", \"email\", \"name\", \"imageUrl\"],\n webhook: \"whsec_ (svix-signed)\",\n onDelete: \"tombstone (never row-delete)\",\n },\n {\n engine: \"@odla-ai/chapter clerk.ts (Clerk Backend API via vault clerk_secret_key)\",\n direction: \"odla->provider\",\n entity: \"clerk user\",\n // Separate metadata fields so a public role write cannot expose or\n // clobber backend-only account/profile signals.\n fields: [\n \"public_metadata.role\",\n \"private_metadata.applicationId\",\n \"private_metadata.profile\",\n ],\n onDelete: \"n/a (writes only)\",\n },\n ],\n provision: {\n human: [\n \"Run `npx clerk auth login` — the one interactive step; the agent then creates + configures the Clerk app with the Clerk CLI (no pk_ to hand-paste).\",\n 'For auth mode \"full\": create the Clerk user-sync webhook and store its whsec_, plus the sk_ as clerk_secret_key, in the tenant vault (Studio, write-only).',\n ],\n cli: [\n \"Clerk CLI (`npx clerk apps create/link/config patch`) creates + configures the instance and pulls the pk_.\",\n \"odla `provision` records it: setAuth(env, publishableKey) -> apps-registry (issuer/JWKS derived from the key).\",\n ],\n doctor: [\n \"registry auth[env] present when the app mounts <SignIn>?\",\n 'auth mode \"full\" => whsec_ and clerk_secret_key present in the tenant vault?',\n ],\n },\n};\n","// The member session — what GET /api/me returns to a signed-in applicant/member.\n// Ported from the reference application's summary + /api/me reconciliation. The\n// SHAPING is pure and package-enforced so no site re-derives it; the worker owns\n// only the I/O around it (locating the application by email, reconciling the\n// meeting against the calendar) and hands the resolved rows here.\n//\n// Two invariants live here, not in a site:\n// - `paid` is DERIVED, never a stored flag: a subscription exists and the\n// application wasn't refunded. Sites can't drift a stale boolean out of sync\n// with Stripe.\n// - the live meeting row wins: its startAt/meetUrl/timezone override whatever\n// the application row cached, and a non-scheduled meeting (a cancellation\n// adopted from the calendar) forces meetingAt back to null.\n\n/** An application row, as far as the session cares about it. */\nexport interface ApplicationRecord {\n id: string;\n firstName?: string | null;\n lastName?: string | null;\n email?: string | null;\n status: string;\n meetingAt?: number | null;\n meetingLink?: string | null;\n createdAt?: number | null;\n stripeSubscriptionId?: string | null;\n renewalAt?: number | null;\n canceled?: boolean;\n tierId?: string | null;\n}\n\n/** The reconciled meeting row (already adopted against the calendar), or null. */\nexport interface MeetingRecord {\n status: string;\n startAt?: number | null;\n meetUrl?: string | null;\n timezone?: string | null;\n}\n\n/** The stable, non-meeting fields of an application (safe to expose to its own\n * owner). */\nexport interface ApplicationSummary {\n id: string;\n firstName: string | null;\n lastName: string | null;\n email: string | null;\n status: string;\n createdAt: number | null;\n meetingLink: string | null;\n paid: boolean;\n renewalAt: number | null;\n canceled: boolean;\n /** Server-authoritative membership tier selected on this application. */\n tierId: string | null;\n}\n\n/** A summary plus the reconciled meeting fields — the `application` the member\n * area renders. */\nexport interface MemberApplication extends ApplicationSummary {\n meetingAt: number | null;\n meetUrl: string | null;\n timezone: string;\n}\n\n/** The full GET /api/me payload for a signed-in user. */\nexport interface MemberSession {\n userId: string;\n email: string | null;\n role: string;\n superAdmin: boolean;\n application: MemberApplication | null;\n}\n\n/** Derive the summary fields from an application row. `paid` is computed, not\n * read, so it can never contradict Stripe. */\nexport function applicationSummary(app: ApplicationRecord): ApplicationSummary {\n return {\n id: app.id,\n firstName: app.firstName ?? null,\n lastName: app.lastName ?? null,\n email: app.email ?? null,\n status: app.status,\n createdAt: app.createdAt ?? null,\n meetingLink: app.meetingLink ?? null,\n paid: Boolean(app.stripeSubscriptionId) && app.status !== \"refunded\",\n renewalAt: app.renewalAt ?? null,\n canceled: app.canceled === true,\n tierId: app.tierId ?? null,\n };\n}\n\n/** Fold a (possibly absent, already-reconciled) meeting into the application the\n * member area renders. The live meeting overrides the application's cached\n * meeting fields; a non-`scheduled` meeting clears the booking. */\nexport function memberApplication(\n app: ApplicationRecord,\n meeting: MeetingRecord | null | undefined,\n defaultTimezone: string,\n): MemberApplication {\n const summary = applicationSummary(app);\n let meetingAt = app.meetingAt ?? null;\n let meetUrl: string | null = null;\n let timezone = defaultTimezone;\n if (meeting) {\n timezone = meeting.timezone ?? timezone;\n if (meeting.status === \"scheduled\") {\n meetingAt = meeting.startAt ?? null;\n meetUrl = meeting.meetUrl ?? null;\n } else {\n meetingAt = null;\n }\n }\n return { ...summary, meetingAt, meetUrl, timezone };\n}\n\n/** Identity of the signed-in user, from the verified session. */\nexport interface SessionUser {\n userId: string;\n email?: string | null;\n role: string;\n}\n\n/** Assemble the GET /api/me payload. `application` is null when the user has no\n * application on file (an admin who never applied, or a brand-new account). */\nexport function memberSession(\n user: SessionUser,\n opts: { application: MemberApplication | null; superAdmin: boolean },\n): MemberSession {\n return {\n userId: user.userId,\n email: user.email ?? null,\n role: user.role,\n superAdmin: opts.superAdmin,\n application: opts.application,\n };\n}\n","// Brand tokens (H4). defineChapter accepts a `brand` block; this turns it into a\n// `:root { --…: … }` CSS block, so a chapter re-skins the WHOLE UI — the\n// @odla-ai/ui components, the admin shell, and the member islands, which all read\n// --ui-* design tokens — from one config instead of hand-writing inline CSS.\n//\n// Pure string generation, so it is unit-testable and can be emitted at\n// build/SSR time into the page <head> (no flash of unstyled content), or via the\n// <BrandStyle> component from @odla-ai/chapter/ui.\nimport type { ChapterBrand, ChapterBrandTokens } from \"./types\";\n\n// A palette entry is either a direct custom property (already `--…`, e.g.\n// `--ui-accent` to retheme components) or a bare name we expose as `--<name>`\n// (e.g. `moss` → `--moss`, for a site to reference in its own CSS).\nfunction paletteVar(key: string): string {\n return key.startsWith(\"--\") ? key : `--${key}`;\n}\n\n// Strip characters that could break out of a `--var: value;` declaration or the\n// surrounding <style>. Brand config is trusted author input, so this is a\n// belt-and-suspenders guard, not a security boundary.\nfunction cleanValue(value: string): string {\n return value.replace(/[<>{};]/g, \"\").trim();\n}\n\nfunction paletteDecls(palette: Record<string, string> | undefined): string[] {\n const decls: string[] = [];\n for (const [key, value] of Object.entries(palette ?? {})) {\n if (typeof value === \"string\" && value.trim()) decls.push(`${paletteVar(key)}: ${cleanValue(value)};`);\n }\n return decls;\n}\n\nconst TOKEN_VARS: Record<keyof ChapterBrandTokens, string> = {\n background: \"--ui-bg\",\n surface: \"--ui-surface\",\n surface2: \"--ui-surface-2\",\n text: \"--ui-text\",\n textMuted: \"--ui-text-muted\",\n textFaint: \"--ui-text-faint\",\n border: \"--ui-border\",\n borderStrong: \"--ui-border-strong\",\n accent: \"--ui-accent\",\n accentStrong: \"--ui-accent-strong\",\n accentSoft: \"--ui-accent-soft\",\n onAccent: \"--ui-on-accent\",\n good: \"--ui-good\",\n warn: \"--ui-warn\",\n danger: \"--ui-danger\",\n chart1: \"--ui-chart-1\",\n chart2: \"--ui-chart-2\",\n chart3: \"--ui-chart-3\",\n chart4: \"--ui-chart-4\",\n chart5: \"--ui-chart-5\",\n chart6: \"--ui-chart-6\",\n chartPositive: \"--ui-chart-pos\",\n chartNegative: \"--ui-chart-neg\",\n contentWidth: \"--ui-content-width\",\n panelRadius: \"--ui-radius-lg\",\n panelShadow: \"--ui-shadow\",\n masterDetailColumns: \"--ui-master-detail-columns\",\n masterDetailMinHeight: \"--ui-master-detail-min-height\",\n pagePadding: \"--chapter-admin-page-padding\",\n workspacePadding: \"--chapter-admin-workspace-padding\",\n};\n\nfunction semanticDecls(tokens: ChapterBrandTokens | undefined): string[] {\n return Object.entries(tokens ?? {}).flatMap(([key, value]) =>\n typeof value === \"string\" && value.trim()\n ? [`${TOKEN_VARS[key as keyof ChapterBrandTokens]}: ${cleanValue(value)};`]\n : [],\n );\n}\n\n/**\n * Build the CSS that maps a chapter's brand onto the design tokens the UI reads:\n * each `palette` entry becomes a custom property (light, and dark unless\n * `paletteDark` overrides), and `fonts` (display/body/numeral) map to\n * `--ui-font-display` / `--ui-font-sans` / `--ui-font-numeral`. The dark block is\n * emitted under both `:root[data-theme=\"dark\"]` (the odla-ui theme toggle) and\n * `@media (prefers-color-scheme: dark)`. Returns \"\" when there is nothing to\n * theme. These are brand OVERRIDES on top of a base theme — they do not replace\n * the theme layer the components need (see {@link brandTokens} usage in the docs).\n */\nexport function brandTokens(\n brand: ChapterBrand | undefined,\n options: { selector?: string } = {},\n): string {\n if (!brand) return \"\";\n const light = [...paletteDecls(brand.palette), ...semanticDecls(brand.tokens)];\n const fonts = brand.fonts;\n if (fonts?.display) light.push(`--ui-font-display: ${cleanValue(fonts.display)};`);\n if (fonts?.body) light.push(`--ui-font-sans: ${cleanValue(fonts.body)};`);\n if (fonts?.numeral) light.push(`--ui-font-numeral: ${cleanValue(fonts.numeral)};`);\n const dark = [...paletteDecls(brand.paletteDark), ...semanticDecls(brand.tokensDark)];\n const invert = paletteDecls(brand.paletteInvert);\n const selector = options.selector ?? \":root\";\n const darkSelector = selector === \":root\" ? ':root[data-theme=\"dark\"]' : `${selector}[data-theme=\"dark\"]`;\n const systemSelector = selector === \":root\"\n ? ':root:not([data-theme=\"light\"])'\n : `${selector}:not([data-theme=\"light\"])`;\n\n let css = light.length ? `${selector} {\\n ${light.join(\"\\n \")}\\n}\\n` : \"\";\n if (dark.length) {\n const block = `{\\n ${dark.join(\"\\n \")}\\n}`;\n css += `${darkSelector} ${block}\\n@media (prefers-color-scheme: dark) {\\n ${systemSelector} ${block}\\n}\\n`;\n }\n if (invert.length) {\n const invertSelector = selector === \":root\"\n ? \".ui-invert\"\n : `${selector}.ui-invert, ${selector} .ui-invert`;\n css += `${invertSelector} {\\n color-scheme: dark;\\n ${invert.join(\"\\n \")}\\n}\\n`;\n }\n return css;\n}\n\n/** Structural output accepted from `@odla-ai/brand`'s pure token compiler. */\nexport interface CompiledChapterBrandTokens {\n light: Record<string, string>;\n dark: Record<string, string>;\n}\n\n/**\n * Turn a complete compiled token pair into Chapter's brand contract without\n * coupling Chapter's runtime to the brand-book/agent package. Explicit values in\n * `base` win, so a host can make final per-site adjustments after compilation.\n */\nexport function chapterBrandFromTokens(\n compiled: CompiledChapterBrandTokens,\n base: ChapterBrand = {},\n): ChapterBrand {\n return {\n ...base,\n palette: { ...compiled.light, ...base.palette },\n paletteDark: { ...compiled.dark, ...base.paletteDark },\n paletteInvert: { ...compiled.dark, ...base.paletteInvert },\n };\n}\n","// The Google → chapter half of the bidirectional calendar sync. Booking writes\n// events TO the platform calendar (0.4.0's create/reschedule); this ADOPTS edits\n// FROM it: when the owner moves or cancels the intro call directly in Google,\n// reconcile mirrors that onto our canonical `meetings` row and the `application`\n// projection. Chapter never calls Google — the worker reads live events through\n// @odla-ai/calendar's upcoming() (platform-brokered) and applies the ops this\n// returns. Pure + testable; adoption policy (owner edits win) matches the shipped\n// original production worker.\n\n/** A `meetings` row, as far as reconciliation cares. */\nexport interface MeetingForReconcile {\n id: string;\n applicationId: string;\n googleEventId?: string | null;\n status: string;\n startAt?: number | null;\n endAt?: number | null;\n}\n\n/** One live calendar event (a subset of @odla-ai/calendar's Booking). */\nexport interface LiveEvent {\n eventId: string;\n status?: string;\n startAt?: number;\n endAt?: number;\n}\n\n/** An adopt decision: mirror a Google move/cancel onto our rows. */\nexport interface ReconcileDecision {\n meetingId: string;\n applicationId: string;\n kind: \"cancelled\" | \"moved\";\n /** Attrs to write onto the `meetings` row. */\n meetingPatch: Record<string, unknown>;\n /** Attrs to write onto the `applications` row (the projection). */\n applicationPatch: Record<string, unknown>;\n}\n\n/** Meetings still worth reconciling: a scheduled booking with a Google event that\n * starts in the future (or within the last hour, to catch a just-passed edit). */\nexport function isReconcilable(meeting: MeetingForReconcile, now: number): boolean {\n return meeting.status === \"scheduled\" && Boolean(meeting.googleEventId) && (meeting.startAt ?? 0) > now - 3_600_000;\n}\n\n/**\n * Diff canonical `meetings` against the live calendar events and return the adopt\n * decisions — only for meetings that actually changed (a still-matching meeting\n * is omitted). A meeting whose event vanished or is `cancelled` in Google is\n * adopted as cancelled (application `meetingAt` zeroed — 0 means \"was booked,\n * then cancelled\"); a meeting whose event moved adopts the new window (duration\n * preserved when the event omits `endAt`).\n */\nexport function reconcileMeetings(\n meetings: readonly MeetingForReconcile[],\n events: readonly LiveEvent[],\n now: number,\n): ReconcileDecision[] {\n const byEvent = new Map(events.map((e) => [e.eventId, e]));\n const decisions: ReconcileDecision[] = [];\n for (const m of meetings) {\n if (!isReconcilable(m, now) || !m.googleEventId) continue;\n const g = byEvent.get(m.googleEventId);\n if (!g || g.status === \"cancelled\") {\n decisions.push({\n meetingId: m.id,\n applicationId: m.applicationId,\n kind: \"cancelled\",\n meetingPatch: { status: \"cancelled\", drift: \"none\", adoptedFromGoogleAt: now },\n applicationPatch: { meetingAt: 0, meetingLink: \"\" },\n });\n } else if (g.startAt !== undefined && g.startAt !== m.startAt) {\n const duration = (m.endAt ?? 0) - (m.startAt ?? 0);\n decisions.push({\n meetingId: m.id,\n applicationId: m.applicationId,\n kind: \"moved\",\n meetingPatch: { startAt: g.startAt, endAt: g.endAt ?? g.startAt + duration, drift: \"none\", adoptedFromGoogleAt: now },\n applicationPatch: { meetingAt: g.startAt },\n });\n }\n }\n return decisions;\n}\n","// Scheduling core — config resolution + the booking invariants, ported from the\n// proven production worker. Everything here is PURE (no @odla-ai/calendar, no\n// db), so the correctness properties are unit-testable and package-enforced; the\n// worker route owns only the I/O (FreeBusy, computeBookableSlots, calendar\n// create/reschedule, the db writes) and calls these.\n//\n// Package-enforced invariants:\n// - the `meetings` row is canonical; applications.meetingAt and the calendar\n// event are projections written from it.\n// - one intro event per application, forever: a rebooking RESCHEDULES the\n// existing event (preserving its Meet link + invite thread), never creates a\n// second — see {@link bookingDecision} + {@link introIdempotencyKey}.\n// - status never moves backward on booking; you can only book from a pipeline\n// stage in `bookableFrom` — see `canBook` in ./pipeline + applicationBookingUpdate.\n// - endAt is always derived server-side, never client-supplied — see\n// {@link endForSlot}.\nimport type { ChapterScheduling } from \"./types\";\n\n/** A fully-resolved scheduling config (every field present). */\nexport interface ResolvedScheduling {\n slotMinutes: number;\n days: readonly number[];\n startHour: number;\n endHour: number;\n timezone: string;\n minNoticeHours: number;\n windowDays: number;\n summaryTemplate: string;\n}\n\n/** Proven defaults: 45-minute weekday slots, 9–5 Pacific, 24h notice,\n * a 14-day window. The summary is generic (a chapter's group seed supplies a\n * name-branded one). */\nexport const SCHEDULING_DEFAULTS: ResolvedScheduling = {\n slotMinutes: 45,\n days: [1, 2, 3, 4, 5],\n startHour: 9,\n endHour: 17,\n timezone: \"America/Los_Angeles\",\n minNoticeHours: 24,\n windowDays: 14,\n summaryTemplate: \"Introduction call with {{firstName}} {{lastName}}\",\n};\n\nfunction isValidTimeZone(tz: string): boolean {\n try {\n new Intl.DateTimeFormat(undefined, { timeZone: tz });\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolve a group's scheduling config against the defaults, validating every\n * bound at config-write time (throws on a bad config, so a\n * misconfiguration surfaces immediately rather than yielding empty slots).\n * `windowDays` is capped at 62 because Google FreeBusy is.\n */\nexport function resolveScheduling(config?: ChapterScheduling): ResolvedScheduling {\n const result = validateScheduling(config);\n if (result.ok) return result.value;\n const detail = Object.entries(result.errors)\n .map(([field, message]) => `${field}: ${message}`)\n .join(\" \");\n throw new Error(`scheduling: ${detail}`);\n}\n\n/** Validation messages keyed by form field. */\nexport type SchedulingErrors = Record<string, string>;\n\n/**\n * Validate a scheduling config field by field, collecting owner-readable messages\n * rather than throwing on the first problem. An admin settings form needs to say\n * *which* field is wrong and why — \"pick at least one day\" beats a stack trace —\n * so the admin route returns these directly. {@link resolveScheduling} is the\n * throwing wrapper for internal/config-time use.\n */\nexport function validateScheduling(\n config?: ChapterScheduling,\n): { ok: true; value: ResolvedScheduling } | { ok: false; errors: SchedulingErrors } {\n const d = config ?? {};\n const c: ResolvedScheduling = {\n slotMinutes: d.slotMinutes ?? SCHEDULING_DEFAULTS.slotMinutes,\n days: d.days ?? SCHEDULING_DEFAULTS.days,\n startHour: d.startHour ?? SCHEDULING_DEFAULTS.startHour,\n endHour: d.endHour ?? SCHEDULING_DEFAULTS.endHour,\n timezone: d.timezone ?? SCHEDULING_DEFAULTS.timezone,\n minNoticeHours: d.minNoticeHours ?? SCHEDULING_DEFAULTS.minNoticeHours,\n windowDays: d.windowDays ?? SCHEDULING_DEFAULTS.windowDays,\n summaryTemplate: d.summaryTemplate ?? SCHEDULING_DEFAULTS.summaryTemplate,\n };\n const errors: SchedulingErrors = {};\n if (!(c.slotMinutes >= 15 && c.slotMinutes <= 240)) {\n errors.slotMinutes = \"Slot length must be between 15 and 240 minutes.\";\n }\n if (!(c.windowDays >= 1 && c.windowDays <= 62)) {\n errors.windowDays = \"Booking window must be between 1 and 62 days (the calendar caps look-ahead at 62).\";\n }\n if (!(c.minNoticeHours >= 0 && c.minNoticeHours <= 336)) {\n errors.minNoticeHours = \"Minimum notice must be between 0 and 336 hours.\";\n }\n if (!(c.startHour >= 0 && c.startHour < c.endHour && c.endHour <= 24)) {\n errors.hours = \"Hours must satisfy 0 ≤ start < end ≤ 24.\";\n }\n const days = [...c.days];\n if (!days.length) errors.days = \"Pick at least one day.\";\n else if (!days.every((n) => Number.isInteger(n) && n >= 0 && n <= 6)) {\n errors.days = \"Days must be weekday numbers, 0 (Sunday) through 6 (Saturday).\";\n }\n if (typeof c.timezone !== \"string\" || !isValidTimeZone(c.timezone)) {\n errors.timezone = `\"${String(c.timezone)}\" is not a valid IANA timezone (for example \"America/Los_Angeles\").`;\n }\n if (typeof c.summaryTemplate !== \"string\") errors.summaryTemplate = \"Calendar summary template must be text.\";\n return Object.keys(errors).length > 0 ? { ok: false, errors } : { ok: true, value: { ...c, days } };\n}\n\n/** Statuses a member may book/reschedule from (early pipeline only). */\n// Booking eligibility is answered by the configured pipeline — canBook(status,\n// pipeline) in ./pipeline — not a hardcoded status list, so a chapter that\n// customizes its stages gets one consistent answer.\n\n/** The availability window: `[now, now + windowDays]` in epoch ms. */\nexport function slotWindow(now: number, windowDays: number): { from: number; to: number } {\n return { from: now, to: now + windowDays * 86_400_000 };\n}\n\n/** The slot's end instant, always derived from its start (never client-supplied). */\nexport function endForSlot(startAt: number, slotMinutes: number): number {\n return startAt + slotMinutes * 60_000;\n}\n\n/** Double-book pre-check: the requested start must land exactly on a currently\n * bookable slot boundary. */\nexport function isSlotAvailable(slots: readonly { startAt: number }[], startAt: number): boolean {\n return slots.some((s) => s.startAt === startAt);\n}\n\n/** Render a meeting summary from its template (`{{firstName}}`/`{{lastName}}`). */\nexport function renderSummary(template: string, app: { firstName?: string | null; lastName?: string | null }): string {\n return template.replace(\"{{firstName}}\", app.firstName ?? \"\").replace(\"{{lastName}}\", app.lastName ?? \"\");\n}\n\n/** The prior scheduled meeting for an application, as far as booking cares. */\nexport interface ExistingMeeting {\n id: string;\n googleEventId?: string | null;\n meetUrl?: string | null;\n htmlLink?: string | null;\n}\n\n/** Decide reschedule-vs-create: reschedule iff there's an existing event to move,\n * so the Meet link + invite thread survive and no second event is minted. */\nexport function bookingDecision(existing: ExistingMeeting | null | undefined): { reschedule: boolean; eventId: string | null } {\n const eventId = existing?.googleEventId ?? null;\n return { reschedule: Boolean(eventId), eventId };\n}\n\n/** The create idempotency key — one intro event per application, forever, so a\n * retried create returns the same booking rather than a duplicate. */\nexport function introIdempotencyKey(applicationId: string): string {\n return `application:${applicationId}:intro`;\n}\n\n/** The canonical `meetings` row for a first booking. A `type` (not `interface`)\n * so it stays assignable to a db op's `attrs` (Record<string, unknown>). */\nexport type NewMeetingRow = {\n id: string;\n applicationId: string;\n groupId: string;\n startAt: number;\n endAt: number;\n timezone: string;\n status: \"scheduled\";\n googleEventId: string;\n meetUrl?: string;\n htmlLink?: string;\n drift: \"none\";\n createdAt: number;\n};\n\n/** Build the new `meetings` row after the calendar created the event. Optional\n * scalars are omitted (never null), per the odla-db porting rule. */\nexport function meetingCreateRow(i: {\n meetingId: string;\n applicationId: string;\n groupId: string;\n startAt: number;\n endAt: number;\n timezone: string;\n googleEventId: string;\n meetUrl?: string | null;\n htmlLink?: string | null;\n createdAt: number;\n}): NewMeetingRow {\n return {\n id: i.meetingId,\n applicationId: i.applicationId,\n groupId: i.groupId,\n startAt: i.startAt,\n endAt: i.endAt,\n timezone: i.timezone,\n status: \"scheduled\",\n googleEventId: i.googleEventId,\n ...(i.meetUrl ? { meetUrl: i.meetUrl } : {}),\n ...(i.htmlLink ? { htmlLink: i.htmlLink } : {}),\n drift: \"none\",\n createdAt: i.createdAt,\n };\n}\n\n/** The `meetings`-row patch for a reschedule (same row id, moved in place). */\nexport type MeetingReschedulePatch = {\n startAt: number;\n endAt: number;\n drift: \"none\";\n};\n\n/** Patch to move an existing meeting to a new window. */\nexport function meetingRescheduleUpdate(startAt: number, endAt: number): MeetingReschedulePatch {\n return { startAt, endAt, drift: \"none\" };\n}\n\n/** The `applications`-row patch after a booking. */\nexport type ApplicationBookingPatch = {\n meetingAt: number;\n meetingLink?: string;\n status?: \"call_scheduled\";\n};\n\n/** Project the booking onto the application row: cache the time, adopt the\n * calendar link if any, and advance the status to `call_scheduled` unless it is\n * already there (never backward). */\nexport function applicationBookingUpdate(\n currentStatus: string,\n startAt: number,\n htmlLink?: string | null,\n): ApplicationBookingPatch {\n return {\n meetingAt: startAt,\n ...(htmlLink ? { meetingLink: htmlLink } : {}),\n ...(currentStatus !== \"call_scheduled\" ? { status: \"call_scheduled\" as const } : {}),\n };\n}\n","// Reading tiers out of the database. Kept apart from tiers.ts so the decision\n// logic there stays pure and directly testable, and apart from the route\n// modules so both the join config and the checkout resolve tiers identically —\n// a page that offers a tier the checkout would refuse is the bug this prevents.\nimport type { ChapterDb } from \"./types\";\nimport { offerableTiers, resolveTiers, type ChapterTier, type TierGroup } from \"./tiers\";\n\n/** A `groups` row as the tier loader needs it. */\nexport type TierGroupRow = TierGroup & { id?: string };\n\nfunction rowToTier(row: Record<string, unknown>, groupId: string): ChapterTier {\n return {\n id: String(row.id ?? \"\"),\n groupId: String(row.groupId ?? groupId),\n name: String(row.name ?? \"\"),\n priceCents: typeof row.priceCents === \"number\" ? row.priceCents : 0,\n ...(typeof row.stripePriceId === \"string\" && row.stripePriceId\n ? { stripePriceId: row.stripePriceId }\n : {}),\n ...(typeof row.blurb === \"string\" ? { blurb: row.blurb } : {}),\n sortOrder: typeof row.sortOrder === \"number\" ? row.sortOrder : 0,\n // A row that never set `active` is offered; only an explicit false retires\n // a tier, so a half-seeded row cannot silently hide a membership.\n active: row.active !== false,\n };\n}\n\n/**\n * Every tier a group offers, ordered, including the implicit tier synthesized\n * for a chapter that predates tiers. Never throws on a missing namespace: a\n * deployment whose schema has not been pushed yet reads as \"no rows\", which\n * resolves to the legacy single tier.\n */\nexport async function loadTiers(db: ChapterDb, group: TierGroupRow): Promise<ChapterTier[]> {\n const groupId = String(group.id ?? \"\");\n let rows: unknown;\n try {\n rows = (await db.query({\n tiers: { $: { where: { groupId }, order: { sortOrder: \"asc\" }, limit: 100 } },\n }) as Record<string, unknown>).tiers;\n } catch {\n rows = undefined;\n }\n const list = Array.isArray(rows)\n ? rows.map((row) => rowToTier(row as Record<string, unknown>, groupId))\n : [];\n return resolveTiers(group, list);\n}\n\n/** The tiers a join page may show: active, and joinable as configured. */\nexport async function loadOfferableTiers(\n db: ChapterDb,\n group: TierGroupRow,\n hasSecretKey: boolean,\n): Promise<ChapterTier[]> {\n return offerableTiers(await loadTiers(db, group), group, hasSecretKey);\n}\n","import type { FieldConditions } from \"@odla-ai/crm\";\nimport type { MembershipPageDocument } from \"./membership-page\";\nimport type { ChapterScheduling } from \"./types\";\nimport type { GiftOfferCatalog } from \"./gift-offers\";\n\n/** Current wire-format version for complete signup-control documents. */\nexport const SIGNUP_CONTROL_SCHEMA_VERSION = 1 as const;\n/** Package-owned follower endpoint for signed signup-control delivery. */\nexport const SIGNUP_CONTROL_PATH = \"/api/signup-control\" as const;\n\n/** One authoritative membership tier in a signup-control revision. */\nexport interface SignupControlTier {\n id: string;\n name: string;\n available: boolean;\n sortOrder: number;\n priceCents: number;\n stripePriceId?: string;\n blurb?: string;\n}\n\n/** A bounded application contract. Fields must already exist in the follower schema. */\nexport interface SignupControlApplication {\n required: readonly string[];\n optional: readonly string[];\n conditions?: Readonly<Record<string, FieldConditions>>;\n copy?: Readonly<Record<string, string>>;\n}\n\n/** Delegated legal and trust copy used by the packaged join journey. */\nexport interface SignupControlPolicy {\n disclaimerText: string;\n refundPolicyText: string;\n trustCopy?: string;\n commitmentText?: string;\n normsText?: string;\n}\n\n/** Bounded semantic design tokens delegated to the chapter signup surface. */\nexport interface SignupControlTheme {\n /** Includes color, spacing, and typography tokens such as font families. */\n tokens: Readonly<Record<string, string | number>>;\n}\n\n/** Complete desired state delivered by a controlling hub. */\nexport interface SignupControlDocument {\n schemaVersion: typeof SIGNUP_CONTROL_SCHEMA_VERSION;\n revision: number;\n generatedAt: number;\n source: { appId: string };\n target: { chapterId: string; environment: string; stripeMode: \"test\" | \"live\" };\n tiers: readonly SignupControlTier[];\n membershipPage: MembershipPageDocument;\n application?: SignupControlApplication;\n policy?: SignupControlPolicy;\n scheduling?: ChapterScheduling;\n theme?: SignupControlTheme;\n giftOffers?: GiftOfferCatalog;\n}\n\n/** Digest travels beside the document so the exact desired state is attestable. */\nexport interface SignupControlEnvelope {\n digest: string;\n document: SignupControlDocument;\n}\n\n/** Exact follower acknowledgement for one accepted or replayed revision. */\nexport interface SignupControlReceipt {\n ok: true;\n target: { chapterId: string; environment: string };\n revision: number;\n digest: string;\n status: \"accepted\" | \"replayed\";\n acknowledgedAt: number;\n}\n\n/** Stable reason codes returned when a follower refuses desired state. */\nexport type SignupControlRejection =\n | \"invalid_document\"\n | \"invalid_digest\"\n | \"wrong_source\"\n | \"wrong_target\"\n | \"wrong_environment\"\n | \"wrong_stripe_mode\"\n | \"stale_revision\"\n | \"conflicting_revision\"\n | \"materialization_failed\";\n\n/** Normalized document result returned by the package validator. */\nexport type SignupControlValidation =\n | { ok: true; value: SignupControlDocument }\n | { ok: false; errors: readonly string[] };\n","/** The first stable, shared Chapter membership-page renderer contract. */\nexport const MEMBERSHIP_PAGE_RENDERER = \"membership-cards-v1\" as const;\n\n/** Fixed visual emphasis choices supported by the versioned card renderer. */\nexport type MembershipTierVariant = \"standard\" | \"featured\" | \"supporting\";\n\n/** A bounded, token-rendered aside within one membership card. */\nexport interface MembershipTierCallout {\n label?: string;\n bodyMarkdown: string;\n}\n\n/** Scarcity copy displayed without changing tier availability or checkout. */\nexport interface MembershipTierCapacity {\n total: number;\n label?: string;\n}\n\n/**\n * Presentation attached to one server-authoritative membership tier.\n *\n * Price, free/paid state, identity, and application targeting deliberately do\n * not live here. They are resolved from the public Chapter join config so\n * authored marketing copy can never change what checkout charges.\n */\nexport interface MembershipTierPresentation {\n tierId: string;\n variant?: MembershipTierVariant;\n badge?: string;\n summaryMarkdown?: string;\n priceEyebrow?: string;\n compareAtPriceCents?: number;\n billingLabel?: string;\n priceNoteMarkdown?: string;\n capacity?: MembershipTierCapacity;\n benefits?: readonly string[];\n callout?: MembershipTierCallout;\n ctaLabel?: string;\n}\n\n/** A bounded document that can be reviewed once and rendered by any Chapter host. */\nexport interface MembershipPageDocument {\n schemaVersion: 1;\n renderer: typeof MEMBERSHIP_PAGE_RENDERER;\n tiers: readonly MembershipTierPresentation[];\n footnoteMarkdown?: string;\n}\n\n/** Minimal server-authoritative tier identity and charged amount used during validation. */\nexport interface MembershipTierAuthority {\n id: string;\n priceCents: number;\n}\n\n/** Live tier authority used to reject missing, unknown, or misleading presentation. */\nexport interface MembershipPageValidationOptions {\n /** When supplied, every live tier must occur exactly once in the document. */\n tiers?: readonly MembershipTierAuthority[];\n}\n\n/** A normalized document or the complete actionable list of validation failures. */\nexport type MembershipPageValidationResult =\n | { ok: true; value: MembershipPageDocument }\n | { ok: false; errors: readonly string[] };\n\nconst TIER_ID = /^[a-z][a-z0-9-]{0,79}$/;\nconst VARIANTS = new Set<MembershipTierVariant>([\"standard\", \"featured\", \"supporting\"]);\nconst ROOT_KEYS = new Set([\"schemaVersion\", \"renderer\", \"tiers\", \"footnoteMarkdown\"]);\nconst TIER_KEYS = new Set([\n \"tierId\", \"variant\", \"badge\", \"summaryMarkdown\", \"priceEyebrow\",\n \"compareAtPriceCents\", \"billingLabel\", \"priceNoteMarkdown\", \"capacity\",\n \"benefits\", \"callout\", \"ctaLabel\",\n]);\nconst CALLOUT_KEYS = new Set([\"label\", \"bodyMarkdown\"]);\nconst CAPACITY_KEYS = new Set([\"total\", \"label\"]);\nconst MAX_TIERS = 20;\nconst MAX_BENEFITS = 24;\nconst MAX_MARKDOWN = 65_536;\nconst MAX_LABEL = 160;\n\nconst objectRecord = (value: unknown): Record<string, unknown> | null =>\n value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null;\n\nfunction rejectUnknownKeys(\n value: Record<string, unknown>,\n allowed: ReadonlySet<string>,\n path: string,\n errors: string[],\n): void {\n for (const key of Object.keys(value)) {\n if (!allowed.has(key)) errors.push(`${path}.${key} is not supported`);\n }\n}\n\nfunction boundedString(\n value: unknown,\n path: string,\n errors: string[],\n max: number,\n required = false,\n): string | undefined {\n if (value === undefined) {\n if (required) errors.push(`${path} is required`);\n return undefined;\n }\n if (typeof value !== \"string\") {\n errors.push(`${path} must be a string`);\n return undefined;\n }\n const text = value.trim();\n if (required && !text) errors.push(`${path} is required`);\n if (text.length > max) errors.push(`${path} must be at most ${max.toLocaleString(\"en-US\")} characters`);\n return text;\n}\n\n/**\n * Validate and normalize a membership-page document without evaluating code,\n * accepting HTML, or allowing authored links/styles. Markdown slots are later\n * rendered by @odla-ai/ui's bounded safe Markdown component.\n */\nexport function validateMembershipPageDocument(\n input: unknown,\n options: MembershipPageValidationOptions = {},\n): MembershipPageValidationResult {\n const errors: string[] = [];\n const root = objectRecord(input);\n if (!root) return { ok: false, errors: [\"document must be an object\"] };\n rejectUnknownKeys(root, ROOT_KEYS, \"document\", errors);\n if (root.schemaVersion !== 1) errors.push(\"document.schemaVersion must be 1\");\n if (root.renderer !== MEMBERSHIP_PAGE_RENDERER) {\n errors.push(`document.renderer must be \\\"${MEMBERSHIP_PAGE_RENDERER}\\\"`);\n }\n if (!Array.isArray(root.tiers)) errors.push(\"document.tiers must be an array\");\n const rawTiers = Array.isArray(root.tiers) ? root.tiers : [];\n if (Array.isArray(root.tiers) && rawTiers.length === 0) errors.push(\"document.tiers must include at least one tier\");\n if (rawTiers.length > MAX_TIERS) errors.push(`document.tiers supports at most ${MAX_TIERS} entries`);\n\n const authority = new Map((options.tiers ?? []).map((tier) => [tier.id, tier]));\n const seen = new Set<string>();\n const tiers: MembershipTierPresentation[] = [];\n for (const [index, raw] of rawTiers.slice(0, MAX_TIERS).entries()) {\n const path = `document.tiers[${index}]`;\n const item = objectRecord(raw);\n if (!item) {\n errors.push(`${path} must be an object`);\n continue;\n }\n rejectUnknownKeys(item, TIER_KEYS, path, errors);\n const tierId = boundedString(item.tierId, `${path}.tierId`, errors, 80, true) ?? \"\";\n if (tierId && !TIER_ID.test(tierId)) errors.push(`${path}.tierId must be a lowercase kebab-case id`);\n if (seen.has(tierId)) errors.push(`${path}.tierId duplicates \\\"${tierId}\\\"`);\n seen.add(tierId);\n if (authority.size && !authority.has(tierId)) errors.push(`${path}.tierId \\\"${tierId}\\\" is not an offered tier`);\n\n const variant = item.variant;\n if (variant !== undefined && (typeof variant !== \"string\" || !VARIANTS.has(variant as MembershipTierVariant))) {\n errors.push(`${path}.variant must be standard, featured, or supporting`);\n }\n const compareAt = item.compareAtPriceCents;\n if (compareAt !== undefined && (!Number.isInteger(compareAt) || Number(compareAt) < 0 || Number(compareAt) > 100_000_000)) {\n errors.push(`${path}.compareAtPriceCents must be an integer from 0 to 100,000,000`);\n }\n const actual = authority.get(tierId)?.priceCents;\n if (Number.isInteger(compareAt) && actual !== undefined && Number(compareAt) <= actual) {\n errors.push(`${path}.compareAtPriceCents must be greater than the authoritative tier price`);\n }\n\n let benefits: string[] | undefined;\n if (item.benefits !== undefined) {\n if (!Array.isArray(item.benefits)) errors.push(`${path}.benefits must be an array`);\n else {\n if (item.benefits.length > MAX_BENEFITS) errors.push(`${path}.benefits supports at most ${MAX_BENEFITS} entries`);\n benefits = item.benefits.slice(0, MAX_BENEFITS).flatMap((benefit, benefitIndex) => {\n const text = boundedString(benefit, `${path}.benefits[${benefitIndex}]`, errors, 2_000, true);\n return text ? [text] : [];\n });\n }\n }\n\n let callout: MembershipTierCallout | undefined;\n if (item.callout !== undefined) {\n const rawCallout = objectRecord(item.callout);\n if (!rawCallout) errors.push(`${path}.callout must be an object`);\n else {\n rejectUnknownKeys(rawCallout, CALLOUT_KEYS, `${path}.callout`, errors);\n const bodyMarkdown = boundedString(rawCallout.bodyMarkdown, `${path}.callout.bodyMarkdown`, errors, MAX_MARKDOWN, true);\n const label = boundedString(rawCallout.label, `${path}.callout.label`, errors, MAX_LABEL);\n if (bodyMarkdown) callout = { ...(label ? { label } : {}), bodyMarkdown };\n }\n }\n\n let capacity: MembershipTierCapacity | undefined;\n if (item.capacity !== undefined) {\n const rawCapacity = objectRecord(item.capacity);\n if (!rawCapacity) errors.push(`${path}.capacity must be an object`);\n else {\n rejectUnknownKeys(rawCapacity, CAPACITY_KEYS, `${path}.capacity`, errors);\n const total = rawCapacity.total;\n if (!Number.isInteger(total) || Number(total) < 1 || Number(total) > 1_000_000) {\n errors.push(`${path}.capacity.total must be an integer from 1 to 1,000,000`);\n }\n const label = boundedString(rawCapacity.label, `${path}.capacity.label`, errors, MAX_LABEL);\n if (Number.isInteger(total) && Number(total) >= 1 && Number(total) <= 1_000_000) {\n capacity = { total: Number(total), ...(label ? { label } : {}) };\n }\n }\n }\n\n const badge = boundedString(item.badge, `${path}.badge`, errors, MAX_LABEL);\n const summaryMarkdown = boundedString(item.summaryMarkdown, `${path}.summaryMarkdown`, errors, MAX_MARKDOWN);\n const priceEyebrow = boundedString(item.priceEyebrow, `${path}.priceEyebrow`, errors, MAX_LABEL);\n const billingLabel = boundedString(item.billingLabel, `${path}.billingLabel`, errors, MAX_LABEL);\n const priceNoteMarkdown = boundedString(item.priceNoteMarkdown, `${path}.priceNoteMarkdown`, errors, MAX_MARKDOWN);\n const ctaLabel = boundedString(item.ctaLabel, `${path}.ctaLabel`, errors, MAX_LABEL);\n tiers.push({\n tierId,\n ...(typeof variant === \"string\" && VARIANTS.has(variant as MembershipTierVariant) ? { variant: variant as MembershipTierVariant } : {}),\n ...(badge ? { badge } : {}),\n ...(summaryMarkdown ? { summaryMarkdown } : {}),\n ...(priceEyebrow ? { priceEyebrow } : {}),\n ...(Number.isInteger(compareAt) ? { compareAtPriceCents: Number(compareAt) } : {}),\n ...(billingLabel ? { billingLabel } : {}),\n ...(priceNoteMarkdown ? { priceNoteMarkdown } : {}),\n ...(capacity ? { capacity } : {}),\n ...(benefits ? { benefits } : {}),\n ...(callout ? { callout } : {}),\n ...(ctaLabel ? { ctaLabel } : {}),\n });\n }\n if (authority.size) {\n for (const tierId of authority.keys()) {\n if (!seen.has(tierId)) errors.push(`document.tiers is missing offered tier \\\"${tierId}\\\"`);\n }\n }\n const footnoteMarkdown = boundedString(root.footnoteMarkdown, \"document.footnoteMarkdown\", errors, MAX_MARKDOWN);\n if (errors.length) return { ok: false, errors };\n return {\n ok: true,\n value: {\n schemaVersion: 1,\n renderer: MEMBERSHIP_PAGE_RENDERER,\n tiers,\n ...(footnoteMarkdown ? { footnoteMarkdown } : {}),\n },\n };\n}\n\n/** Validate a document or fail closed with all actionable validation errors. */\nexport function membershipPageDocument(\n input: unknown,\n options: MembershipPageValidationOptions = {},\n): MembershipPageDocument {\n const result = validateMembershipPageDocument(input, options);\n if (!result.ok) throw new TypeError(`Invalid membership page document: ${result.errors.join(\"; \")}`);\n return result.value;\n}\n","import { resolveApplication } from \"./member\";\nimport { validateMembershipPageDocument } from \"./membership-page\";\nimport { validateScheduling } from \"./scheduling\";\nimport { validateGiftOfferCatalog } from \"./gift-offers\";\nimport type {\n SignupControlApplication,\n SignupControlDocument,\n SignupControlPolicy,\n SignupControlTheme,\n SignupControlTier,\n SignupControlValidation,\n} from \"./signup-control-contract\";\n\nconst SLUG = /^[a-z0-9][a-z0-9-]{1,62}$/;\nconst ENVIRONMENT = /^[a-z][a-z0-9_-]{0,62}$/;\nconst TIER = /^[a-z][a-z0-9-]{0,79}$/;\nconst PRICE = /^price_[A-Za-z0-9]{12,}$/;\nconst ROOT_KEYS = new Set([\n \"schemaVersion\", \"revision\", \"generatedAt\", \"source\", \"target\", \"tiers\",\n \"membershipPage\", \"application\", \"policy\", \"scheduling\", \"theme\", \"giftOffers\",\n]);\nconst TIER_KEYS = new Set([\"id\", \"name\", \"available\", \"sortOrder\", \"priceCents\", \"stripePriceId\", \"blurb\"]);\n\nconst recordOf = (value: unknown): Record<string, unknown> | null =>\n value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null;\n\nfunction unknownKeys(value: Record<string, unknown>, allowed: ReadonlySet<string>, path: string, errors: string[]): void {\n for (const key of Object.keys(value)) if (!allowed.has(key)) errors.push(`${path}.${key} is not supported`);\n}\n\nfunction text(value: unknown, path: string, errors: string[], max = 65_536): string {\n if (typeof value !== \"string\" || !value.trim()) {\n errors.push(`${path} is required`);\n return \"\";\n }\n if (value.length > max) errors.push(`${path} must be at most ${max} characters`);\n return value.trim();\n}\n\nfunction tiersOf(value: unknown, errors: string[]): SignupControlTier[] {\n if (!Array.isArray(value) || !value.length) {\n errors.push(\"document.tiers must be a non-empty array\");\n return [];\n }\n if (value.length > 20) errors.push(\"document.tiers supports at most 20 entries\");\n const seen = new Set<string>();\n return value.slice(0, 20).flatMap((raw, index) => {\n const path = `document.tiers[${index}]`;\n const item = recordOf(raw);\n if (!item) {\n errors.push(`${path} must be an object`);\n return [];\n }\n unknownKeys(item, TIER_KEYS, path, errors);\n const id = text(item.id, `${path}.id`, errors, 80);\n if (id && !TIER.test(id)) errors.push(`${path}.id must be a lowercase kebab-case id`);\n if (seen.has(id)) errors.push(`${path}.id duplicates \"${id}\"`);\n seen.add(id);\n const name = text(item.name, `${path}.name`, errors, 160);\n if (typeof item.available !== \"boolean\") errors.push(`${path}.available must be boolean`);\n if (!Number.isInteger(item.sortOrder) || Number(item.sortOrder) < 0) errors.push(`${path}.sortOrder must be a non-negative integer`);\n if (!Number.isInteger(item.priceCents) || Number(item.priceCents) < 0 || Number(item.priceCents) > 100_000_000) {\n errors.push(`${path}.priceCents must be an integer from 0 to 100,000,000`);\n }\n if (item.stripePriceId !== undefined && (typeof item.stripePriceId !== \"string\" || !PRICE.test(item.stripePriceId))) {\n errors.push(`${path}.stripePriceId must be a real Stripe Price id`);\n }\n if (item.available === true && Number(item.priceCents) > 0 && !item.stripePriceId) {\n errors.push(`${path}.stripePriceId is required for an available paid tier`);\n }\n const blurb = item.blurb === undefined ? undefined : text(item.blurb, `${path}.blurb`, errors, 4_000);\n return [{\n id, name, available: item.available === true,\n sortOrder: Number(item.sortOrder) || 0,\n priceCents: Number(item.priceCents) || 0,\n ...(typeof item.stripePriceId === \"string\" ? { stripePriceId: item.stripePriceId } : {}),\n ...(blurb ? { blurb } : {}),\n }];\n });\n}\n\nfunction applicationOf(value: unknown, errors: string[]): SignupControlApplication | undefined {\n if (value === undefined) return undefined;\n const input = recordOf(value);\n if (!input) {\n errors.push(\"document.application must be an object\");\n return undefined;\n }\n unknownKeys(input, new Set([\"required\", \"optional\", \"conditions\", \"copy\"]), \"document.application\", errors);\n try {\n const resolved = resolveApplication(input);\n const copy = recordOf(input.copy);\n if (input.copy !== undefined && (!copy || Object.values(copy).some((item) => typeof item !== \"string\"))) {\n errors.push(\"document.application.copy must contain only string values\");\n }\n return {\n required: resolved.required,\n optional: resolved.optional,\n ...(Object.keys(resolved.conditions).length ? { conditions: resolved.conditions } : {}),\n ...(copy ? { copy: copy as Record<string, string> } : {}),\n };\n } catch (error) {\n errors.push(error instanceof Error ? error.message : \"document.application is invalid\");\n return undefined;\n }\n}\n\nfunction policyOf(value: unknown, errors: string[]): SignupControlPolicy | undefined {\n if (value === undefined) return undefined;\n const input = recordOf(value);\n if (!input) {\n errors.push(\"document.policy must be an object\");\n return undefined;\n }\n const allowed = new Set([\"disclaimerText\", \"refundPolicyText\", \"trustCopy\", \"commitmentText\", \"normsText\"]);\n unknownKeys(input, allowed, \"document.policy\", errors);\n const result = {} as Record<string, string>;\n for (const key of allowed) {\n if (input[key] === undefined && key !== \"disclaimerText\" && key !== \"refundPolicyText\") continue;\n result[key] = text(input[key], `document.policy.${key}`, errors);\n }\n return result as unknown as SignupControlPolicy;\n}\n\nfunction themeOf(value: unknown, errors: string[]): SignupControlTheme | undefined {\n if (value === undefined) return undefined;\n const input = recordOf(value);\n const tokens = recordOf(input?.tokens);\n if (!input || !tokens) {\n errors.push(\"document.theme.tokens must be an object\");\n return undefined;\n }\n unknownKeys(input, new Set([\"tokens\"]), \"document.theme\", errors);\n if (Object.keys(tokens).length > 256) errors.push(\"document.theme.tokens supports at most 256 entries\");\n let serializedLength = 0;\n for (const [key, token] of Object.entries(tokens)) {\n if (!/^--ui-[a-z0-9][a-z0-9-]{0,94}$/.test(key)) {\n errors.push(`document.theme.tokens.${key} must be an allowlisted --ui-* custom property`);\n }\n const rendered = String(token).trim();\n serializedLength += key.length + rendered.length + 4;\n if ((typeof token !== \"string\" && typeof token !== \"number\") ||\n (typeof token === \"number\" && !Number.isFinite(token)) ||\n !rendered || rendered.length > 1_000 ||\n /[\\u0000-\\u001f\\u007f\\\\<>{};]|\\/\\*|\\*\\/|(?:^|[^a-z])(?:url|expression)\\s*\\(|@import/i.test(rendered)) {\n errors.push(`document.theme.tokens.${key} must be a bounded breakout-safe CSS value`);\n }\n }\n if (serializedLength > 65_536) errors.push(\"document.theme.tokens exceeds the serialized size bound\");\n return { tokens: tokens as Record<string, string | number> };\n}\n\n/** Validate and normalize one complete desired signup state. */\nexport function validateSignupControlDocument(input: unknown): SignupControlValidation {\n const errors: string[] = [];\n const root = recordOf(input);\n if (!root) return { ok: false, errors: [\"document must be an object\"] };\n unknownKeys(root, ROOT_KEYS, \"document\", errors);\n if (root.schemaVersion !== 1) errors.push(\"document.schemaVersion must be 1\");\n if (!Number.isSafeInteger(root.revision) || Number(root.revision) < 1) errors.push(\"document.revision must be a positive integer\");\n if (!Number.isSafeInteger(root.generatedAt) || Number(root.generatedAt) < 1) errors.push(\"document.generatedAt must be epoch milliseconds\");\n const source = recordOf(root.source);\n const target = recordOf(root.target);\n const appId = text(source?.appId, \"document.source.appId\", errors, 63);\n const chapterId = text(target?.chapterId, \"document.target.chapterId\", errors, 63);\n const environment = text(target?.environment, \"document.target.environment\", errors, 63);\n if (appId && !SLUG.test(appId)) errors.push(\"document.source.appId must be a lowercase app slug\");\n if (chapterId && !SLUG.test(chapterId)) errors.push(\"document.target.chapterId must be a lowercase app slug\");\n if (environment && !ENVIRONMENT.test(environment)) errors.push(\"document.target.environment is invalid\");\n if (target?.stripeMode !== \"test\" && target?.stripeMode !== \"live\") errors.push(\"document.target.stripeMode must be test or live\");\n const tiers = tiersOf(root.tiers, errors);\n const available = tiers.filter((tier) => tier.available).sort((a, b) => a.sortOrder - b.sortOrder);\n const page = validateMembershipPageDocument(root.membershipPage, { tiers: available });\n if (!page.ok) errors.push(...page.errors);\n else if (page.value.tiers.some((tier, index) => tier.tierId !== available[index]?.id)) {\n errors.push(\"document.membershipPage.tiers must follow the available tier display order\");\n }\n const application = applicationOf(root.application, errors);\n const policy = policyOf(root.policy, errors);\n let scheduling;\n if (root.scheduling !== undefined) {\n const checked = validateScheduling(root.scheduling as never);\n if (!checked.ok) errors.push(...Object.entries(checked.errors).map(([key, value]) => `document.scheduling.${key}: ${value}`));\n else scheduling = root.scheduling;\n }\n const theme = themeOf(root.theme, errors);\n const giftOffers = root.giftOffers === undefined\n ? undefined\n : validateGiftOfferCatalog(root.giftOffers, new Set(tiers.map((tier) => tier.id)));\n if (giftOffers && !giftOffers.ok) errors.push(...giftOffers.errors);\n if (errors.length || !page.ok) return { ok: false, errors };\n return { ok: true, value: {\n schemaVersion: 1,\n revision: Number(root.revision),\n generatedAt: Number(root.generatedAt),\n source: { appId },\n target: { chapterId, environment, stripeMode: target?.stripeMode as \"test\" | \"live\" },\n tiers,\n membershipPage: page.value,\n ...(application ? { application } : {}),\n ...(policy ? { policy } : {}),\n ...(scheduling ? { scheduling } : {}),\n ...(theme ? { theme } : {}),\n ...(giftOffers?.ok ? { giftOffers: giftOffers.value } : {}),\n } };\n}\n","import type { SignupControlTheme } from \"./signup-control-contract\";\n\n/** Stable marker a static document can place where managed signup tokens belong. */\nexport const SIGNUP_CONTROL_THEME_MARKER = \"<!--odla:signup-control-theme-->\" as const;\n/** Stable id shared by the server renderer and browser hydration helper. */\nexport const SIGNUP_CONTROL_THEME_STYLE_ID = \"odla-signup-control-theme\" as const;\n\nconst TOKEN_NAME = /^--ui-[a-z0-9][a-z0-9-]{0,94}$/;\nconst DIGEST = /^sha256:[0-9a-f]{64}$/;\nconst UNSAFE_VALUE = /[\\u0000-\\u001f\\u007f\\\\<>{};]|\\/\\*|\\*\\/|(?:^|[^a-z])(?:url|expression)\\s*\\(|@import/i;\nconst MAX_TOKENS = 256;\nconst MAX_VALUE_LENGTH = 1_000;\nconst MAX_SERIALIZED_LENGTH = 65_536;\n\n/** The active revision shape exposed by `GET /api/join-config`. */\nexport interface SignupControlThemeRevision {\n revision: number;\n digest: string;\n theme?: SignupControlTheme;\n}\n\n/** Identity shared by initial HTML, response caching, and client hydration. */\nexport interface SignupControlThemeMetadata {\n source: \"active\" | \"bootstrap\";\n revision: number | null;\n digest: string | null;\n /** Include this value in any host-owned cache key for transformed HTML. */\n cacheKey: string;\n}\n\n/** A validated style block ready to place in an HTML head. */\nexport interface SignupControlThemeHead {\n css: string;\n head: string;\n metadata: SignupControlThemeMetadata;\n}\n\n/** Minimal DOM surface required by {@link hydrateSignupControlTheme}. */\nexport interface SignupControlThemeStyleTarget {\n textContent: string | null;\n getAttribute(name: string): string | null;\n setAttribute(name: string, value: string): void;\n removeAttribute(name: string): void;\n}\n\n/** Host-owned fallback inputs shared by server rendering and hydration. */\nexport interface SignupControlThemeOptions {\n /** Local site-owned tokens used only when no active managed revision exists. */\n bootstrapTokens?: Readonly<Record<string, string | number>>;\n}\n\nfunction validatedTokens(\n input: Readonly<Record<string, string | number>> | undefined,\n): Readonly<Record<string, string>> {\n const entries = Object.entries(input ?? {});\n if (entries.length > MAX_TOKENS) {\n throw new TypeError(`signup-control theme supports at most ${MAX_TOKENS} tokens`);\n }\n const tokens: Record<string, string> = {};\n let serializedLength = 0;\n for (const [name, raw] of entries.sort(([left], [right]) => left.localeCompare(right))) {\n if (!TOKEN_NAME.test(name)) {\n throw new TypeError(`signup-control theme token \"${name}\" must be an allowlisted --ui-* property`);\n }\n if ((typeof raw !== \"string\" && typeof raw !== \"number\") ||\n (typeof raw === \"number\" && !Number.isFinite(raw))) {\n throw new TypeError(`signup-control theme token \"${name}\" must be a finite string or number`);\n }\n const value = String(raw).trim();\n if (!value || value.length > MAX_VALUE_LENGTH || UNSAFE_VALUE.test(value)) {\n throw new TypeError(`signup-control theme token \"${name}\" has an unsafe or oversized value`);\n }\n serializedLength += name.length + value.length + 4;\n if (serializedLength > MAX_SERIALIZED_LENGTH) {\n throw new TypeError(\"signup-control theme exceeds the serialized size bound\");\n }\n tokens[name] = value;\n }\n return tokens;\n}\n\nfunction cssFor(tokens: Readonly<Record<string, string>>): string {\n const declarations = Object.entries(tokens).map(([name, value]) => ` ${name}: ${value};`);\n return declarations.length ? `:root {\\n${declarations.join(\"\\n\")}\\n}` : \"\";\n}\n\nfunction stateFor(\n revision: SignupControlThemeRevision | null,\n options: SignupControlThemeOptions,\n): { css: string; metadata: SignupControlThemeMetadata } {\n if (!revision) {\n return {\n css: cssFor(validatedTokens(options.bootstrapTokens)),\n metadata: { source: \"bootstrap\", revision: null, digest: null, cacheKey: \"signup-control:bootstrap\" },\n };\n }\n if (!Number.isSafeInteger(revision.revision) || revision.revision < 1 || !DIGEST.test(revision.digest)) {\n throw new TypeError(\"signup-control theme revision metadata is invalid\");\n }\n return {\n css: cssFor(validatedTokens(revision.theme?.tokens)),\n metadata: {\n source: \"active\",\n revision: revision.revision,\n digest: revision.digest,\n cacheKey: `signup-control:${revision.digest}`,\n },\n };\n}\n\nfunction attributes(metadata: SignupControlThemeMetadata): string {\n return [\n `id=\"${SIGNUP_CONTROL_THEME_STYLE_ID}\"`,\n `data-signup-control-source=\"${metadata.source}\"`,\n `data-signup-control-cache-key=\"${metadata.cacheKey}\"`,\n ...(metadata.revision === null ? [] : [`data-signup-control-revision=\"${metadata.revision}\"`]),\n ...(metadata.digest === null ? [] : [`data-signup-control-digest=\"${metadata.digest}\"`]),\n ].join(\" \");\n}\n\n/**\n * Render validated signup-control tokens for the initial HTML head. Passing\n * `null` emits the deterministic local bootstrap state; it never performs I/O.\n */\nexport function renderSignupControlThemeHead(\n revision: SignupControlThemeRevision | null,\n options: SignupControlThemeOptions = {},\n): SignupControlThemeHead {\n const { css, metadata } = stateFor(revision, options);\n return { css, metadata, head: `<style ${attributes(metadata)}>${css}</style>` };\n}\n\n/**\n * Replace the stable marker (preferred), an earlier Chapter style block, or the\n * closing head tag. The returned HTML always contains exactly one managed block.\n */\nexport function injectSignupControlThemeHead(\n html: string,\n rendered: SignupControlThemeHead,\n marker: string = SIGNUP_CONTROL_THEME_MARKER,\n): string {\n const existing = /<style\\b(?=[^>]*\\bid\\s*=\\s*[\"']odla-signup-control-theme[\"'])[^>]*>[\\s\\S]*?<\\/style>/gi;\n const existingBlocks = html.match(existing) ?? [];\n if (existingBlocks.length > 1) {\n throw new TypeError(\"signup-control theme style block must appear at most once\");\n }\n if (existingBlocks.length === 1) return html.replace(existing, rendered.head);\n const markerIndex = html.indexOf(marker);\n if (markerIndex >= 0) {\n if (html.indexOf(marker, markerIndex + marker.length) >= 0) {\n throw new TypeError(\"signup-control theme marker must appear exactly once\");\n }\n return `${html.slice(0, markerIndex)}${rendered.head}${html.slice(markerIndex + marker.length)}`;\n }\n const closingHead = html.search(/<\\/head\\s*>/i);\n if (closingHead < 0) throw new TypeError(\"signup-control theme requires an HTML head\");\n return `${html.slice(0, closingHead)}${rendered.head}${html.slice(closingHead)}`;\n}\n\n/**\n * Apply a newly fetched revision to the server-rendered style element. When the\n * revision and digest already match, this performs no writes and returns false,\n * so hydration cannot cause a visual token change.\n */\nexport function hydrateSignupControlTheme(\n target: SignupControlThemeStyleTarget,\n revision: SignupControlThemeRevision | null,\n options: SignupControlThemeOptions = {},\n): boolean {\n const next = stateFor(revision, options);\n const currentSource = target.getAttribute(\"data-signup-control-source\");\n const currentRevision = target.getAttribute(\"data-signup-control-revision\");\n const currentDigest = target.getAttribute(\"data-signup-control-digest\");\n if (currentSource === next.metadata.source &&\n currentRevision === (next.metadata.revision === null ? null : String(next.metadata.revision)) &&\n currentDigest === next.metadata.digest) {\n return false;\n }\n target.textContent = next.css;\n target.setAttribute(\"data-signup-control-source\", next.metadata.source);\n target.setAttribute(\"data-signup-control-cache-key\", next.metadata.cacheKey);\n if (next.metadata.revision === null) target.removeAttribute(\"data-signup-control-revision\");\n else target.setAttribute(\"data-signup-control-revision\", String(next.metadata.revision));\n if (next.metadata.digest === null) target.removeAttribute(\"data-signup-control-digest\");\n else target.setAttribute(\"data-signup-control-digest\", next.metadata.digest);\n return true;\n}\n","import type { MembershipTierPresentation } from \"./membership-page\";\n\n/** A presentation overlay parsed from the constrained membership Markdown convention. */\nexport type MembershipTierMarkdownResult =\n | { ok: true; value: MembershipTierPresentation }\n | { ok: false; errors: readonly string[] };\n\nconst MAX_BENEFITS = 24;\nconst MAX_MARKDOWN = 65_536;\nconst MAX_LABEL = 160;\nconst MARKDOWN_SECTION = /^##\\s+(.+?)\\s*$/;\nconst MARKDOWN_HEADING = /^#{1,6}\\s+/;\nconst MARKDOWN_BENEFIT = /^\\s*[-*+]\\s+(.+?)\\s*$/;\n\ntype MembershipMarkdownSection = \"summary\" | \"benefits\" | \"priceNote\" | \"callout\" | \"action\";\n\nfunction markdownSection(rawHeading: string): { section?: MembershipMarkdownSection; calloutLabel?: string } {\n const heading = rawHeading.trim();\n const normalized = heading.toLowerCase();\n if (normalized === \"summary\") return { section: \"summary\" };\n if (normalized === \"benefits\") return { section: \"benefits\" };\n if (normalized === \"price note\" || normalized === \"rate note\") return { section: \"priceNote\" };\n if (normalized === \"action\" || normalized === \"call to action\") return { section: \"action\" };\n const callout = heading.match(/^callout(?:\\s*[:—-]\\s*(.+))?$/i);\n if (callout) return { section: \"callout\", ...(callout[1]?.trim() ? { calloutLabel: callout[1].trim() } : {}) };\n return {};\n}\n\nfunction markdownBenefits(lines: readonly string[], path: string, errors: string[]): string[] {\n const benefits: string[] = [];\n for (const [index, line] of lines.entries()) {\n if (!line.trim()) continue;\n const match = line.match(MARKDOWN_BENEFIT);\n if (!match) {\n errors.push(`${path} line ${index + 1} must be a Markdown bullet`);\n continue;\n }\n const text = (match[1] ?? \"\").trim();\n if (text.length > 2_000) errors.push(`${path} line ${index + 1} must be at most 2,000 characters`);\n if (text) benefits.push(text);\n }\n if (benefits.length > MAX_BENEFITS) errors.push(`${path} supports at most ${MAX_BENEFITS} entries`);\n return benefits.slice(0, MAX_BENEFITS);\n}\n\n/**\n * Apply authored Markdown to the text slots of an existing tier presentation.\n *\n * The convention is deliberately small and reviewable:\n * - prelude prose -> summary; prelude bullets -> benefits\n * - `## Summary`, `## Benefits`, `## Price note`, `## Callout: Label`,\n * and `## Action` target those exact renderer slots\n *\n * Identity, price, scarcity, variants, badges, links, HTML, and CSS remain in\n * the reviewed presentation/authority contract and cannot be authored here.\n */\nexport function applyMembershipTierMarkdown(\n presentation: MembershipTierPresentation,\n source: string,\n): MembershipTierMarkdownResult {\n if (typeof source !== \"string\") return { ok: false, errors: [\"membership Markdown must be a string\"] };\n if (source.length > MAX_MARKDOWN) {\n return { ok: false, errors: [`membership Markdown must be at most ${MAX_MARKDOWN.toLocaleString(\"en-US\")} characters`] };\n }\n if (!source.trim()) return { ok: true, value: { ...presentation } };\n\n const errors: string[] = [];\n const sections = new Map<MembershipMarkdownSection, { lines: string[]; calloutLabel?: string }>();\n const prelude: string[] = [];\n let current: MembershipMarkdownSection | null = null;\n for (const [index, line] of source.replace(/\\r\\n?/g, \"\\n\").split(\"\\n\").entries()) {\n const heading = line.match(MARKDOWN_SECTION);\n if (heading) {\n const headingText = heading[1] ?? \"\";\n const parsed = markdownSection(headingText);\n if (!parsed.section) {\n errors.push(`membership Markdown heading \"${headingText.trim()}\" is not supported`);\n current = null;\n continue;\n }\n if (sections.has(parsed.section)) {\n errors.push(`membership Markdown repeats the ${parsed.section} section`);\n current = parsed.section;\n continue;\n }\n sections.set(parsed.section, { lines: [], ...(parsed.calloutLabel ? { calloutLabel: parsed.calloutLabel } : {}) });\n current = parsed.section;\n continue;\n }\n if (MARKDOWN_HEADING.test(line)) {\n errors.push(`membership Markdown line ${index + 1} uses an unsupported heading`);\n continue;\n }\n if (current) sections.get(current)?.lines.push(line);\n else prelude.push(line);\n }\n\n const preludeBenefits: string[] = [];\n const preludeSummary: string[] = [];\n for (const line of prelude) {\n const benefit = line.match(MARKDOWN_BENEFIT);\n if (benefit) preludeBenefits.push((benefit[1] ?? \"\").trim());\n else preludeSummary.push(line);\n }\n if (preludeBenefits.length > MAX_BENEFITS) errors.push(`membership Markdown prelude supports at most ${MAX_BENEFITS} benefits`);\n if (preludeBenefits.some((benefit) => benefit.length > 2_000)) errors.push(\"membership Markdown benefits must be at most 2,000 characters\");\n\n const summarySection = sections.get(\"summary\");\n const benefitsSection = sections.get(\"benefits\");\n const priceNoteSection = sections.get(\"priceNote\");\n const calloutSection = sections.get(\"callout\");\n const actionSection = sections.get(\"action\");\n const summaryMarkdown = (summarySection?.lines ?? preludeSummary).join(\"\\n\").trim();\n const benefits = benefitsSection\n ? markdownBenefits(benefitsSection.lines, \"membership Markdown Benefits\", errors)\n : preludeBenefits.filter(Boolean).slice(0, MAX_BENEFITS);\n const priceNoteMarkdown = priceNoteSection?.lines.join(\"\\n\").trim();\n const calloutBody = calloutSection?.lines.join(\"\\n\").trim();\n const actionLines = actionSection?.lines.filter((line) => line.trim());\n const ctaLabel = actionLines?.join(\" \").trim();\n if (actionLines && actionLines.length !== 1) errors.push(\"membership Markdown Action must contain exactly one line\");\n if (ctaLabel && ctaLabel.length > MAX_LABEL) errors.push(`membership Markdown Action must be at most ${MAX_LABEL} characters`);\n if (calloutSection && !calloutBody) errors.push(\"membership Markdown Callout must include body copy\");\n if (calloutSection?.calloutLabel && calloutSection.calloutLabel.length > MAX_LABEL) {\n errors.push(`membership Markdown Callout label must be at most ${MAX_LABEL} characters`);\n }\n if (errors.length) return { ok: false, errors };\n\n return {\n ok: true,\n value: {\n ...presentation,\n ...(summaryMarkdown ? { summaryMarkdown } : {}),\n ...(benefitsSection || preludeBenefits.length ? { benefits } : {}),\n ...(priceNoteSection ? { priceNoteMarkdown: priceNoteMarkdown ?? \"\" } : {}),\n ...(calloutSection ? {\n callout: {\n ...(calloutSection.calloutLabel || presentation.callout?.label\n ? { label: calloutSection.calloutLabel ?? presentation.callout?.label }\n : {}),\n bodyMarkdown: calloutBody ?? \"\",\n },\n } : {}),\n ...(actionSection && ctaLabel ? { ctaLabel } : {}),\n },\n };\n}\n\n/** Apply constrained membership Markdown or fail closed with actionable errors. */\nexport function membershipTierPresentationFromMarkdown(\n presentation: MembershipTierPresentation,\n source: string,\n): MembershipTierPresentation {\n const result = applyMembershipTierMarkdown(presentation, source);\n if (!result.ok) throw new TypeError(`Invalid membership Markdown: ${result.errors.join(\"; \")}`);\n return result.value;\n}\n","import {\n canonicalPromotionValue,\n type PromotionAdapterResult,\n type PromotionArtifactInput,\n type PromotionExclusion,\n} from \"@odla-ai/promotion\";\nimport { signupControlDigest } from \"./signup-control-canonical\";\nimport type { SignupControlDocument } from \"./signup-control-contract\";\nimport { validateSignupControlDocument } from \"./signup-control-validate\";\n\n/** Stable adapter identity bound into Chapter artifact provenance. */\nexport const CHAPTER_PROMOTION_ADAPTER = \"@odla-ai/chapter/v1\";\n\n/** One exact, digest-verified signup-control revision to export. */\nexport interface ChapterPromotionInput {\n document: SignupControlDocument;\n digest: string;\n}\n\nconst exclusions = (chapterId: string, paidTierIds: string[]): PromotionExclusion[] => [\n {\n kind: \"chapter.providers\", id: chapterId, reason: \"provider_identity\",\n paths: [\n ...paidTierIds.map((id) => `tiers[${id}].stripePriceId`),\n \"groups.stripePublishableKey\", \"applications.stripeCustomerId\",\n \"applications.stripeSubscriptionId\", \"meetings.googleEventId\",\n ],\n detail: \"Stripe, Clerk, and Google identities are resolved independently in each target environment.\",\n },\n {\n kind: \"chapter.runtime\", id: chapterId, reason: \"runtime_state\",\n paths: [\"applications.*\", \"meetings.*\", \"emailLog.*\", \"crm_*.*\"],\n detail: \"Applicants, meetings, messages, and CRM rows are operational state, not managed signup content.\",\n },\n {\n kind: \"chapter.access\", id: chapterId, reason: \"personal_data\",\n paths: [\"admins.*\", \"superAdmins.*\", \"networkNotes.*\"],\n detail: \"People, access lists, and private network notes remain local to the target environment.\",\n },\n {\n kind: \"chapter.history\", id: chapterId, reason: \"authority_history\",\n paths: [\"signupControls[active=false]\", \"signupControls.*At\", \"signupControls.environment\"],\n detail: \"The source retains immutable delivery history; only selected published content is exported.\",\n },\n];\n\n/** Export the provider-independent pieces of one exact active signup revision. */\nexport async function exportChapterPromotion(input: ChapterPromotionInput): Promise<PromotionAdapterResult> {\n if (!/^sha256:[0-9a-f]{64}$/.test(input.digest)) throw new TypeError(\"chapter promotion digest is invalid\");\n const checked = validateSignupControlDocument(input.document);\n if (!checked.ok) throw new TypeError(checked.errors.join(\"; \"));\n const document = checked.value;\n if (await signupControlDigest(document) !== input.digest) throw new TypeError(\"chapter promotion digest does not match its document\");\n const revision = `chapter:${document.target.chapterId}:${document.revision}`;\n const promotionProvenance = {\n adapter: CHAPTER_PROMOTION_ADAPTER,\n sourceIds: [`signup-control:${document.revision}`, document.source.appId, document.target.chapterId].sort(),\n receiptDigests: [input.digest as `sha256:${string}`],\n };\n const artifact = (kind: string, id: string, content: unknown): PromotionArtifactInput => ({\n kind, id, sourceRevision: revision, provenance: promotionProvenance,\n content: canonicalPromotionValue(content),\n });\n const chapterId = document.target.chapterId;\n const artifacts = [\n artifact(\"chapter.catalog\", chapterId, {\n chapterId,\n tiers: document.tiers.map(({ stripePriceId: _providerId, ...tier }) => tier),\n }),\n artifact(\"chapter.membership-page\", chapterId, document.membershipPage),\n ...(document.application ? [artifact(\"chapter.application\", chapterId, document.application)] : []),\n ...(document.policy ? [artifact(\"chapter.policy\", chapterId, document.policy)] : []),\n ...(document.scheduling ? [artifact(\"chapter.scheduling\", chapterId, document.scheduling)] : []),\n ...(document.theme ? [artifact(\"chapter.theme\", chapterId, document.theme)] : []),\n ];\n return {\n adapter: CHAPTER_PROMOTION_ADAPTER,\n artifacts,\n exclusions: exclusions(chapterId, document.tiers.filter((tier) => tier.stripePriceId).map((tier) => tier.id)),\n preconditions: [\n {\n code: \"chapter.signup-control.schema\", path: \"services.chapter.signupControl.schemaVersion\", expected: document.schemaVersion,\n detail: \"The target must support this Chapter signup-control document version.\",\n },\n {\n code: \"chapter.identity\", path: \"app.appId\", expected: chapterId,\n detail: \"Chapter content can only target the chapter named by the signed source revision.\",\n },\n ],\n };\n}\n"],"mappings":"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","names":["allowed","id","paymentsReady","tiers","attr","attr","id","attr","id","superAdmins","id","text","DEFAULT_REQUIRED","DEFAULT_OPTIONAL","SLUG","SLUG","SECRET_NAME","SLUG","id","rows","tiers","SLUG","allowed","tiers","id","SLUG","value","tiers","record","text","emailLog","id","str","encoder","canonicalValue","record","ID","EMAIL_RE","id","ID","record","allowed","id","record","createRecord","updateRecord","updateRecord","createRecord","verifyStripeSignature","id","id","record","meetings","rows","ROOT_KEYS","MAX_MARKDOWN","allowed","text","tiers","SLUG","PRICE","ROOT_KEYS","TIER_KEYS","unknownKeys","allowed","text","id","tiers","MAX_BENEFITS","MAX_MARKDOWN","MAX_LABEL","text","id"]}
|