@nodii/onboarding 0.1.0-dev.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -0
- package/dist/chunk-AZE3NPSY.js +186 -0
- package/dist/chunk-AZE3NPSY.js.map +1 -0
- package/dist/{chunk-BQCTDU5V.js → chunk-BMQINH6O.js} +89 -15
- package/dist/chunk-BMQINH6O.js.map +1 -0
- package/dist/{chunk-34BQX2KR.js → chunk-F75ZJERM.js} +41 -6
- package/dist/chunk-F75ZJERM.js.map +1 -0
- package/dist/chunk-FIRSA7EH.js +3 -0
- package/dist/{chunk-ZDY2I6KY.js.map → chunk-FIRSA7EH.js.map} +1 -1
- package/dist/{chunk-SWMIIUXR.js → chunk-IPAKPLIF.js} +590 -92
- package/dist/chunk-IPAKPLIF.js.map +1 -0
- package/dist/chunk-JFDQZ3AC.js +3 -0
- package/dist/chunk-JFDQZ3AC.js.map +1 -0
- package/dist/{chunk-4SWOVHZ2.js → chunk-KQTS47FC.js} +129 -17
- package/dist/chunk-KQTS47FC.js.map +1 -0
- package/dist/chunk-LVJM4CTG.js +306 -0
- package/dist/chunk-LVJM4CTG.js.map +1 -0
- package/dist/chunk-SEKNVHD3.js +59 -0
- package/dist/chunk-SEKNVHD3.js.map +1 -0
- package/dist/chunk-SIMLMQPT.js +37 -0
- package/dist/chunk-SIMLMQPT.js.map +1 -0
- package/dist/chunk-U56GQITG.js +79 -0
- package/dist/chunk-U56GQITG.js.map +1 -0
- package/dist/{chunk-AFCJLUPK.js → chunk-U6AXKGYQ.js} +14 -5
- package/dist/chunk-U6AXKGYQ.js.map +1 -0
- package/dist/{chunk-AW7W3HAC.js → chunk-XJTJPBJB.js} +40 -3
- package/dist/chunk-XJTJPBJB.js.map +1 -0
- package/dist/client-CqE2dF9A.d.ts +86 -0
- package/dist/consent/index.d.ts +59 -0
- package/dist/consent/index.js +7 -0
- package/dist/consent/index.js.map +1 -0
- package/dist/controller-BQb62D0N.d.ts +177 -0
- package/dist/dynamic/index.d.ts +57 -6
- package/dist/dynamic/index.js +4 -2
- package/dist/errors-vJkye4a0.d.ts +110 -0
- package/dist/form/index.d.ts +2 -2
- package/dist/form/index.js +2 -2
- package/dist/index-Dqfa890U.d.ts +83 -0
- package/dist/index.d.ts +12 -6
- package/dist/index.js +12 -8
- package/dist/{model-IEyDI54w.d.ts → model-ESLSEbi0.d.ts} +199 -46
- package/dist/model-mnjAEtKe.d.ts +253 -0
- package/dist/render-DC7P2BGQ.js +5 -0
- package/dist/render-DC7P2BGQ.js.map +1 -0
- package/dist/schema-BrXb9gnh.d.ts +267 -0
- package/dist/{signup-client-Bl6eUrxR.d.ts → signup-client-BL5DfarJ.d.ts} +152 -19
- package/dist/spec/index.d.ts +10 -81
- package/dist/spec/index.js +3 -2
- package/dist/submit/index.d.ts +7 -71
- package/dist/submit/index.js +3 -3
- package/dist/viewer/index.d.ts +4 -0
- package/dist/viewer/index.js +5 -0
- package/dist/viewer/index.js.map +1 -0
- package/dist/widget/index.d.ts +50 -7
- package/dist/widget/index.js +9 -7
- package/package.json +21 -2
- package/dist/chunk-34BQX2KR.js.map +0 -1
- package/dist/chunk-4SWOVHZ2.js.map +0 -1
- package/dist/chunk-AFCJLUPK.js.map +0 -1
- package/dist/chunk-AW7W3HAC.js.map +0 -1
- package/dist/chunk-BIFANV7M.js +0 -22
- package/dist/chunk-BIFANV7M.js.map +0 -1
- package/dist/chunk-BQCTDU5V.js.map +0 -1
- package/dist/chunk-SWMIIUXR.js.map +0 -1
- package/dist/chunk-ZDY2I6KY.js +0 -3
- package/dist/schema-TfyBU6JW.d.ts +0 -107
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/dynamic/derive.ts","../src/dynamic/stepper.ts"],"names":["z"],"mappings":"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","file":"chunk-KQTS47FC.js","sourcesContent":["/**\n * Spec → Zod validator derivation (D540 §3).\n *\n * Turns arbitrary SpecField descriptors from the served spec into Zod\n * schemas for CLIENT-side UX validation. The server re-validates\n * authoritatively (D540 §2) — client validation is a convenience layer,\n * so the derivation is deliberately conservative:\n *\n * - Known `type`s map to typed schemas (see FIELD TYPE MAP below).\n * - An UNKNOWN type falls back to z.string() (never blocks a field the\n * server knows how to validate).\n * - Known `validation` keys are applied (minLength, maxLength, min, max,\n * pattern, format:\"email\"). Unknown validation keys are IGNORED\n * client-side — the server enforces them.\n * - `required:false` fields accept undefined AND \"\" (an empty input is\n * \"not provided\").\n * - select/radio values must be one of `options`; multiselect values\n * must be a subset.\n *\n * FIELD TYPE MAP:\n * text | textarea | tel | (unknown) → string\n * email → string().email()\n * number → coerce.number (DOM inputs are strings)\n * checkbox | boolean → boolean\n * select | radio → string ∈ options\n * multiselect → string[] ⊆ options\n * date → string, parseable as a date\n */\n\nimport { z } from \"zod/v3\";\nimport type { SpecField, SpecStep } from \"../spec/model.js\";\n\n/** Extract the comparable value of an option entry ({value}, {key}, or scalar). */\nexport function optionValue(option: unknown): string {\n if (option !== null && typeof option === \"object\") {\n const o = option as Record<string, unknown>;\n if (\"value\" in o) return String(o[\"value\"]);\n if (\"key\" in o) return String(o[\"key\"]);\n }\n return String(option);\n}\n\ninterface KnownValidation {\n minLength?: number;\n maxLength?: number;\n min?: number;\n max?: number;\n pattern?: string;\n format?: string;\n}\n\nfunction knownValidation(field: SpecField): KnownValidation {\n const v = field.validation ?? {};\n const out: KnownValidation = {};\n if (typeof v[\"minLength\"] === \"number\") out.minLength = v[\"minLength\"];\n if (typeof v[\"maxLength\"] === \"number\") out.maxLength = v[\"maxLength\"];\n if (typeof v[\"min\"] === \"number\") out.min = v[\"min\"];\n if (typeof v[\"max\"] === \"number\") out.max = v[\"max\"];\n if (typeof v[\"pattern\"] === \"string\") out.pattern = v[\"pattern\"];\n if (typeof v[\"format\"] === \"string\") out.format = v[\"format\"];\n return out;\n}\n\nfunction stringSchema(field: SpecField): z.ZodTypeAny {\n const v = knownValidation(field);\n let s = z.string();\n if (field.type === \"email\" || v.format === \"email\") {\n s = s.email(`${field.label} must be a valid email`);\n }\n if (v.minLength !== undefined) {\n s = s.min(\n v.minLength,\n `${field.label} must be at least ${v.minLength} characters`,\n );\n }\n if (v.maxLength !== undefined) {\n s = s.max(\n v.maxLength,\n `${field.label} must be at most ${v.maxLength} characters`,\n );\n }\n if (v.pattern !== undefined) {\n try {\n s = s.regex(\n new RegExp(v.pattern),\n `${field.label} has an invalid format`,\n );\n } catch {\n // Invalid regex in the spec — skip client-side; server enforces.\n }\n }\n return s;\n}\n\nfunction numberSchema(field: SpecField): z.ZodTypeAny {\n const v = knownValidation(field);\n let s = z.coerce.number({\n invalid_type_error: `${field.label} must be a number`,\n });\n if (v.min !== undefined) {\n s = s.min(v.min, `${field.label} must be at least ${v.min}`);\n }\n if (v.max !== undefined) {\n s = s.max(v.max, `${field.label} must be at most ${v.max}`);\n }\n return s;\n}\n\nfunction enumSchema(field: SpecField): z.ZodTypeAny {\n const allowed = (field.options ?? []).map(optionValue);\n if (allowed.length === 0) return z.string();\n return z.string().refine((val) => allowed.includes(val), {\n message: `${field.label} must be one of the offered options`,\n });\n}\n\nfunction multiEnumSchema(field: SpecField): z.ZodTypeAny {\n const allowed = (field.options ?? []).map(optionValue);\n const item =\n allowed.length === 0\n ? z.string()\n : z.string().refine((val) => allowed.includes(val), {\n message: `${field.label} contains a value outside the offered options`,\n });\n return z.array(item);\n}\n\nfunction dateSchema(field: SpecField): z.ZodTypeAny {\n return z.string().refine((val) => !Number.isNaN(Date.parse(val)), {\n message: `${field.label} must be a valid date`,\n });\n}\n\n/** Derive the value schema for one field, BEFORE the required/optional wrap. */\nfunction baseSchema(field: SpecField): z.ZodTypeAny {\n switch (field.type) {\n case \"email\":\n return stringSchema(field);\n case \"number\":\n return numberSchema(field);\n case \"checkbox\":\n case \"boolean\":\n return z.boolean();\n case \"select\":\n case \"radio\":\n return enumSchema(field);\n case \"multiselect\":\n return multiEnumSchema(field);\n case \"date\":\n return dateSchema(field);\n default:\n // text | textarea | tel | any unknown type → string with validation\n return stringSchema(field);\n }\n}\n\n/**\n * Derive the full Zod schema for one SpecField.\n * Optional fields accept undefined and \"\" (\"not provided\" in a form UI).\n * Required fields additionally reject \"\" for string-typed inputs.\n */\nexport function deriveFieldSchema(field: SpecField): z.ZodTypeAny {\n const base = baseSchema(field);\n if (field.required) {\n // Required string inputs must be non-empty.\n if (\n field.type !== \"checkbox\" &&\n field.type !== \"boolean\" &&\n field.type !== \"number\" &&\n field.type !== \"multiselect\"\n ) {\n return z\n .string({ required_error: `${field.label} is required` })\n .min(1, `${field.label} is required`)\n .pipe(base);\n }\n if (field.type === \"number\") {\n // A required number must be PRESENT. Without this guard,\n // z.coerce.number(\"\") coerces the empty DOM value to 0 and passes —\n // then buildSubmitPayload drops the \"\" answer, so the client declares\n // the form valid while the server 422s on a missing required field.\n // Reject empty/missing BEFORE coercion; a provided value flows to\n // the coercing number schema (min/max still apply).\n return z\n .any()\n .refine(\n (val) => val !== \"\" && val !== undefined && val !== null,\n `${field.label} is required`,\n )\n .pipe(base);\n }\n if (field.type === \"multiselect\") {\n return base.refine(\n (val) => Array.isArray(val) && val.length > 0,\n `${field.label} requires at least one selection`,\n );\n }\n return base;\n }\n // Optional: \"\" normalizes to undefined before validation.\n return z.preprocess(\n (val) =>\n val === \"\" || val === undefined || val === null ? undefined : val,\n base.optional(),\n );\n}\n\n/**\n * Derive a STRICT Zod object schema for one step's fields — unknown answer\n * keys within the step are rejected (mirrors the server's authoritative\n * re-validation posture; a stale client must not silently carry fields the\n * spec no longer defines).\n */\nexport function deriveStepSchema(step: SpecStep) {\n const shape: Record<string, z.ZodTypeAny> = {};\n for (const field of step.fields) {\n shape[field.key] = deriveFieldSchema(field);\n }\n return z.object(shape).strict();\n}\n\n/**\n * Derive the STRICT schema for the complete answers object across all\n * steps (used at submit time and by the 409-stale re-validation).\n */\nexport function deriveAnswersSchema(steps: SpecStep[]) {\n const shape: Record<string, z.ZodTypeAny> = {};\n for (const step of steps) {\n for (const field of step.fields) {\n shape[field.key] = deriveFieldSchema(field);\n }\n }\n return z.object(shape).strict();\n}\n","/**\n * Headless dynamic signup stepper (D540 §1/§3).\n *\n * The steps are GENERATED from the served spec: fields bucket by `stage`\n * server-side → the spec's forms.signup.steps array. More configured\n * fields ⇒ more steps. The final `activation` stage carries the\n * service-selection inputs feeding the existing terminal-stage guards.\n *\n * Framework-agnostic: same subscribe/mutate contract as the Phase-1\n * contact-form state. The default component layer renders it; framework\n * integrations can wrap it.\n *\n * 409 spec_stale flow (D540 reject-stale): the CALLER (widget/submit\n * orchestration) refetches the spec on OnboardingSpecStaleError and calls\n * `applyNewSpec(newSpec)`. The stepper re-validates every answer against\n * the NEW derived schema, DROPS answers whose fields no longer exist,\n * marks `specStale: true`, and repositions to the first step with errors —\n * the user re-confirms; the SDK NEVER silently auto-resubmits.\n */\n\nimport { z, type ZodIssue } from \"zod/v3\";\nimport type { OnboardingSpec, SpecStep, TerminalStage } from \"../spec/model.js\";\nimport { deriveAnswersSchema, deriveStepSchema } from \"./derive.js\";\nimport {\n createConsentController,\n type ConsentController,\n type ConsentState,\n type ConsentSubmitDocument,\n} from \"../consent/controller.js\";\nimport type { FieldError } from \"../form/state.js\";\n\nexport type StepperStatus = \"editing\" | \"submitting\" | \"success\" | \"error\";\n\nexport interface SignupConsent {\n tosAccepted: boolean;\n privacyAccepted: boolean;\n}\n\nexport interface SignupCredentials {\n email: string;\n displayName: string;\n organisationName: string;\n subdomain: string;\n}\n\nexport interface SignupStepperState {\n /** Zero-based index of the current step. */\n stepIndex: number;\n stepCount: number;\n currentStep: SpecStep | null;\n /** Answers keyed by field key (only keys defined by the active spec). */\n answers: Record<string, unknown>;\n /** Derived from serviceSelection-flagged answers (see buildSubmitPayload). */\n selectedServices: string[];\n /** Validation errors for the CURRENT step (or full-form at submit). */\n errors: FieldError[];\n /** Credential/consent errors (submit-time). */\n accountErrors: FieldError[];\n consent: SignupConsent;\n credentials: SignupCredentials;\n status: StepperStatus;\n serverError: string | null;\n /** True after a 409-stale spec swap until the user re-validates. */\n specStale: boolean;\n /** The specVersion currently driving the form (echoed on submit). */\n specVersion: string;\n /** Set on success from the submit response. */\n terminalStage: TerminalStage | null;\n /**\n * D543 ConsentPack state (per-document acceptance + gates). Empty\n * (documents:[]) when the spec serves no consentPack — the consent stage is\n * then skipped and does not gate the submit.\n */\n consentState: ConsentState;\n /**\n * True after a 409 consent_stale swap until the user re-accepts the changed\n * docs. Distinct from specStale — a doc-version bump does not necessarily\n * change the form fields, and the banner copy differs.\n */\n consentStale: boolean;\n /** Keys of the consent docs whose acceptance was reset by the last swap. */\n staleConsentKeys: string[];\n /** Consent-stage errors (submit-time; e.g. a required doc not accepted). */\n consentErrors: FieldError[];\n}\n\nexport type SignupStepperListener = (state: SignupStepperState) => void;\n\n/** The locked credential constraints (PublicOnboardingSubmitRequest). */\nconst credentialsSchema = z.object({\n email: z.string().email(\"A valid account email is required\"),\n displayName: z.string().trim().min(1, \"Your name is required\").max(200),\n organisationName: z\n .string()\n .trim()\n .min(1, \"Organisation name is required\")\n .max(200),\n subdomain: z\n .string()\n .trim()\n .min(1, \"Workspace subdomain is required\")\n .max(63),\n});\n\nfunction zodIssuesToFieldErrors(issues: ZodIssue[]): FieldError[] {\n return issues.map((issue) => ({\n path: issue.path.join(\".\"),\n message: issue.message,\n }));\n}\n\n/** Flatten a serviceSelection field's answer into service ids. */\nfunction serviceIdsOf(key: string, value: unknown): string[] {\n if (typeof value === \"string\" && value !== \"\") return [value];\n if (Array.isArray(value)) return value.map((v) => String(v));\n if (value === true) return [key];\n return [];\n}\n\nexport interface SignupStepperControl {\n getState(): SignupStepperState;\n setAnswer(key: string, value: unknown): void;\n setConsent(consent: Partial<SignupConsent>): void;\n setCredentials(credentials: Partial<SignupCredentials>): void;\n /**\n * The headless ConsentPack controller (D543 §5). Exposed so the default\n * component layer AND fully custom tenant UIs drive the SAME state: mark\n * scroll/open evidence, set acceptance, read per-doc gate status. The\n * stepper subscribes to it internally so consent mutations re-emit stepper\n * state (consentState/consentStale) to the widget.\n */\n readonly consent: ConsentController;\n /** Validate ONLY the current step. Returns true when clean. */\n validateStep(): boolean;\n /** Validate current step; advance when clean. Returns true if advanced. */\n next(): boolean;\n back(): void;\n isFirstStep(): boolean;\n isLastStep(): boolean;\n /**\n * Full-form validation: every step's answers + credentials + consent.\n * Populates errors/accountErrors. Returns true when submittable.\n */\n validateAll(): boolean;\n /**\n * The submit payload body (minus botToken, which the transport attaches).\n * Call ONLY after validateAll() returns true.\n *\n * D543 §4: `consent.documents` is the per-doc consent array built from the\n * ACTUAL consent state (omitted when the spec serves no consentPack). The\n * booleans stay as the derived convenience. THROWS if any required consent\n * doc is not accepted at its gate (never fabricates acceptance).\n */\n buildSubmitPayload(): {\n specVersion: string;\n answers: Record<string, unknown>;\n selectedServices?: string[];\n consent: {\n tosAccepted: true;\n privacyAccepted: true;\n documents?: ConsentSubmitDocument[];\n };\n credentials: { email: string; displayName?: string };\n organisationName?: string;\n subdomain: string;\n };\n /**\n * Swap in a refetched spec after 409 spec_stale. Drops answers for\n * removed fields, re-validates the rest, marks specStale, repositions\n * to the first step with errors. ALSO swaps the consentPack (a spec bump\n * may carry new doc versions) — changed docs require re-acceptance. NEVER\n * auto-resubmits.\n */\n applyNewSpec(spec: OnboardingSpec): void;\n /** Clear the specStale flag once the user has re-confirmed. */\n acknowledgeSpecStale(): void;\n /**\n * Swap in the refetched spec's consentPack after 409 consent_stale (D543\n * §4). Resets acceptance for docs whose version/hash changed (re-acceptance\n * required — NEVER auto-accept a changed doc), marks consentStale, records\n * which keys were reset. NEVER auto-resubmits.\n */\n applyNewConsentPack(spec: OnboardingSpec): void;\n /** Clear the consentStale flag once the user has re-accepted. */\n acknowledgeConsentStale(): void;\n setSubmitting(): void;\n setSuccess(terminalStage: TerminalStage): void;\n setError(message: string): void;\n /**\n * Reset to the pristine initial state against the CURRENT spec: step 0,\n * status \"editing\", answers/credentials/consent/errors cleared. This is\n * the only transition back OUT of \"success\"/\"error\"; the widget's reset()\n * relies on it (otherwise a post-success keystroke would re-emit\n * status \"success\" and re-hide the form).\n */\n reset(): void;\n subscribe(listener: SignupStepperListener): () => void;\n}\n\n/**\n * Create a headless stepper for the spec's signup form.\n *\n * @example\n * ```ts\n * const spec = await fetchOnboardingSpec({ baseUrl, onboarder });\n * const stepper = createSignupStepper(spec);\n * stepper.subscribe(render);\n * stepper.setAnswer(\"company_name\", \"ACME\");\n * if (stepper.next()) { ... }\n * ```\n */\nexport function createSignupStepper(\n spec: OnboardingSpec,\n): SignupStepperControl {\n let steps: SpecStep[] = spec.forms.signup.steps;\n let specVersion = spec.specVersion;\n\n // D543 ConsentPack controller. The stepper OWNS it; the widget + custom\n // UIs drive it via the exposed `consent` control. It's the same instance\n // for the stepper's lifetime — applyNewConsentPack SWAPS its docs in place\n // (createConsentController is re-run on reset()).\n let consentController = createConsentController(spec.consentPack);\n\n let state: SignupStepperState = {\n stepIndex: 0,\n stepCount: steps.length,\n currentStep: steps[0] ?? null,\n answers: {},\n selectedServices: [],\n errors: [],\n accountErrors: [],\n consent: { tosAccepted: false, privacyAccepted: false },\n credentials: {\n email: \"\",\n displayName: \"\",\n organisationName: \"\",\n subdomain: \"\",\n },\n status: \"editing\",\n serverError: null,\n specStale: false,\n specVersion,\n terminalStage: null,\n consentState: consentController.getState(),\n consentStale: false,\n staleConsentKeys: [],\n consentErrors: [],\n };\n\n // Which step indices have been validated at least once. Once a step has\n // been validated, EVERY subsequent setAnswer revalidates it — so a\n // fix-then-rebreak on that step re-shows the error immediately (matching\n // the Phase-1 contact-form `hasValidated` fix). Before a step is validated,\n // typing does not spray errors. Cleared on reset()/applyNewSpec.\n let validatedSteps = new Set<number>();\n\n // True once validateAll() has run — after that, EVERY consent mutation\n // recomputes consent errors (fix-then-rebreak parity with field errors), so\n // a per-doc error clears live as the user accepts and persists as long as a\n // required doc is unmet. Cleared on reset()/applyNewSpec/applyNewConsentPack.\n let consentValidated = false;\n\n const listeners = new Set<SignupStepperListener>();\n\n function emit(): void {\n for (const listener of listeners) {\n listener(structuredClone(state));\n }\n }\n\n /**\n * Mirror the consent controller's state into the stepper state and re-emit,\n * so a subscriber that only watches stepper state (the widget) sees consent\n * gate/acceptance changes. Once validateAll() has run, consent errors are\n * recomputed on every mutation so they clear live AND persist correctly\n * regardless of which emit (validateAll vs a consent mutation vs the async\n * viewer's scroll report) fires last.\n */\n function syncConsentState(): void {\n const consentState = consentController.getState();\n const consentErrors = consentValidated\n ? computeConsentErrors()\n : state.consentErrors;\n state = { ...state, consentState, consentErrors };\n emit();\n }\n\n // Wire consent mutations through the stepper so the widget re-renders. The\n // subscription lives for the controller's lifetime; on reset() a NEW\n // controller is created and re-subscribed.\n let unsubscribeConsent = consentController.subscribe(() =>\n syncConsentState(),\n );\n\n /** One error per required consent doc that is not accepted at its gate. */\n function computeConsentErrors(): FieldError[] {\n const errors: FieldError[] = [];\n for (const d of consentController.getState().documents) {\n if (d.doc.required && !(d.accepted && d.gateSatisfied)) {\n const need =\n d.doc.acceptanceLevel === \"scroll_then_accept\" && !d.gateSatisfied\n ? \"scroll to the end, then accept\"\n : d.doc.acceptanceLevel === \"open_then_accept\" && !d.gateSatisfied\n ? \"open the document, then accept\"\n : \"accept\";\n errors.push({\n path: d.key,\n message: `You must ${need} \"${d.doc.title}\".`,\n });\n }\n }\n return errors;\n }\n\n function knownFieldKeys(): Set<string> {\n const keys = new Set<string>();\n for (const step of steps) {\n for (const field of step.fields) keys.add(field.key);\n }\n return keys;\n }\n\n /** Answers restricted to the current step's fields. */\n function stepAnswers(step: SpecStep): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const field of step.fields) {\n if (field.key in state.answers) out[field.key] = state.answers[field.key];\n }\n return out;\n }\n\n function deriveSelectedServices(): string[] {\n const services: string[] = [];\n for (const step of steps) {\n for (const field of step.fields) {\n if (field.serviceSelection === true) {\n services.push(...serviceIdsOf(field.key, state.answers[field.key]));\n }\n }\n }\n return [...new Set(services)];\n }\n\n /**\n * The EFFECTIVE tos/privacy booleans (D543 §4 \"derived convenience\").\n *\n * When the spec serves a consentPack containing a `tos` / `privacy` doc,\n * the boolean is DERIVED from whether that doc is accepted (the array is\n * authoritative). Otherwise (pre-ConsentPack onboarder), the explicit\n * checkbox booleans from setConsent() apply. This keeps the legacy\n * booleans truthful without letting them contradict the consent array.\n */\n function effectiveConsentBooleans(): SignupConsent {\n if (consentController.isEmpty()) return { ...state.consent };\n const byType = new Map<string, boolean>();\n for (const d of consentController.getState().documents) {\n byType.set(d.doc.docType, d.accepted && d.gateSatisfied);\n }\n return {\n tosAccepted: byType.has(\"tos\")\n ? byType.get(\"tos\") === true\n : state.consent.tosAccepted,\n privacyAccepted: byType.has(\"privacy\")\n ? byType.get(\"privacy\") === true\n : state.consent.privacyAccepted,\n };\n }\n\n function runStepValidation(step: SpecStep): FieldError[] {\n const result = deriveStepSchema(step).safeParse(stepAnswers(step));\n return result.success ? [] : zodIssuesToFieldErrors(result.error.issues);\n }\n\n /**\n * Swap the consent controller's docs to the new spec's consentPack, RESET\n * acceptance for docs whose version/hash changed (re-acceptance required —\n * never auto-accept), and fold the result into stepper state. Shared by\n * applyNewSpec (a spec bump may also bump doc versions) and\n * applyNewConsentPack (a pure consent_stale swap). Returns the reset keys.\n *\n * `controllerAlreadyEmitted`: applyNewPack emits through the controller's\n * own subscription (syncConsentState), so the caller need not re-emit for\n * the consent slice — but callers that ALSO mutate other stepper state\n * fold it into their single state update to avoid a double render.\n */\n function swapConsentPack(newSpec: OnboardingSpec): string[] {\n const resetKeys = consentController.applyNewPack(newSpec.consentPack);\n return resetKeys;\n }\n\n function firstStepWithErrors(): number {\n for (let i = 0; i < steps.length; i++) {\n const step = steps[i];\n if (step && runStepValidation(step).length > 0) return i;\n }\n return 0;\n }\n\n return {\n get consent() {\n return consentController;\n },\n\n getState() {\n return structuredClone(state);\n },\n\n setAnswer(key, value) {\n state = {\n ...state,\n answers: { ...state.answers, [key]: value },\n };\n state.selectedServices = deriveSelectedServices();\n // Live-revalidate once THIS step has been validated at least once —\n // regardless of whether errors are currently showing. This is the\n // fix-then-rebreak fix: after fixing a field (errors → 0), breaking it\n // again must re-show the error without a fresh next()/validateStep().\n if (validatedSteps.has(state.stepIndex) && state.currentStep) {\n state = { ...state, errors: runStepValidation(state.currentStep) };\n }\n emit();\n },\n\n setConsent(consent) {\n state = { ...state, consent: { ...state.consent, ...consent } };\n emit();\n },\n\n setCredentials(credentials) {\n state = {\n ...state,\n credentials: { ...state.credentials, ...credentials },\n };\n emit();\n },\n\n validateStep() {\n if (!state.currentStep) return true;\n validatedSteps.add(state.stepIndex);\n const errors = runStepValidation(state.currentStep);\n state = { ...state, errors };\n emit();\n return errors.length === 0;\n },\n\n next() {\n if (!state.currentStep) return false;\n validatedSteps.add(state.stepIndex);\n const errors = runStepValidation(state.currentStep);\n if (errors.length > 0) {\n state = { ...state, errors };\n emit();\n return false;\n }\n if (state.stepIndex >= steps.length - 1) return false;\n const stepIndex = state.stepIndex + 1;\n state = {\n ...state,\n stepIndex,\n currentStep: steps[stepIndex] ?? null,\n errors: [],\n };\n emit();\n return true;\n },\n\n back() {\n if (state.stepIndex === 0) return;\n const stepIndex = state.stepIndex - 1;\n state = {\n ...state,\n stepIndex,\n currentStep: steps[stepIndex] ?? null,\n errors: [],\n };\n emit();\n },\n\n isFirstStep() {\n return state.stepIndex === 0;\n },\n\n isLastStep() {\n return state.stepIndex >= steps.length - 1;\n },\n\n validateAll() {\n // A full validation counts as validating every step.\n for (let i = 0; i < steps.length; i++) validatedSteps.add(i);\n // Answers across ALL steps (strict — unknown keys rejected).\n const answersResult = deriveAnswersSchema(steps).safeParse(state.answers);\n const errors = answersResult.success\n ? []\n : zodIssuesToFieldErrors(answersResult.error.issues);\n\n // Credentials + consent (locked submit contract).\n const accountErrors: FieldError[] = [];\n const credResult = credentialsSchema.safeParse(state.credentials);\n if (!credResult.success) {\n accountErrors.push(...zodIssuesToFieldErrors(credResult.error.issues));\n }\n // The tos/privacy booleans are the EFFECTIVE (derived-from-consentPack\n // when present) values. This keeps the legacy booleans in lockstep with\n // the ConsentPack — a user who accepted the tos DOC satisfies tosAccepted\n // without a separate checkbox, and one who did NOT is blocked here.\n const effective = effectiveConsentBooleans();\n if (effective.tosAccepted !== true) {\n accountErrors.push({\n path: \"tosAccepted\",\n message: \"You must accept the Terms of Service\",\n });\n }\n if (effective.privacyAccepted !== true) {\n accountErrors.push({\n path: \"privacyAccepted\",\n message: \"You must accept the Privacy Policy\",\n });\n }\n\n // D543 consent stage: every REQUIRED consent doc must be accepted at its\n // gate. Empty consentPack ⇒ vacuously complete (no consentErrors). Mark\n // consent validated so subsequent mutations recompute errors live.\n consentValidated = true;\n const consentErrors = consentController.isEmpty()\n ? []\n : computeConsentErrors();\n\n state = {\n ...state,\n errors,\n accountErrors,\n consentErrors,\n consentState: consentController.getState(),\n };\n emit();\n return (\n errors.length === 0 &&\n accountErrors.length === 0 &&\n consentErrors.length === 0\n );\n },\n\n buildSubmitPayload() {\n // COMPLIANCE-CRITICAL: never fabricate legal consent. Read the ACTUAL\n // consent state and refuse to build a payload unless the user genuinely\n // accepted both. A headless caller that skips validateAll() must not be\n // able to transmit consent:true for a user who never consented. The\n // booleans are the EFFECTIVE (consentPack-derived when present) values.\n const effective = effectiveConsentBooleans();\n if (\n effective.tosAccepted !== true ||\n effective.privacyAccepted !== true\n ) {\n throw new Error(\n \"buildSubmitPayload: cannot build a submit payload without genuine \" +\n \"user consent (tosAccepted && privacyAccepted must both be true). \" +\n \"Call validateAll() and surface the consent errors to the user first.\",\n );\n }\n\n // D543 §4: the consent-document array is authoritative. This THROWS if\n // any REQUIRED doc is not accepted at its gate (never fabricates\n // acceptance) — the same compliance discipline as the booleans above.\n // Omitted (undefined) when the spec serves no consentPack.\n const consentDocuments = consentController.isEmpty()\n ? undefined\n : consentController.buildConsentPayload();\n\n // Run answers through the derived schema so the wire carries COERCED\n // typed values (e.g. number fields as numbers, not raw DOM strings) —\n // this is the exact validation validateAll() applies, so a payload can\n // only be built from a state that would pass. A required field that is\n // empty/missing FAILS here (see deriveFieldSchema's required wrap),\n // so buildSubmitPayload throws rather than silently dropping it.\n const parsed = deriveAnswersSchema(steps).safeParse(state.answers);\n if (!parsed.success) {\n const detail = parsed.error.issues\n .map((i) => `${i.path.join(\".\") || \"(answers)\"}: ${i.message}`)\n .join(\"; \");\n throw new Error(\n `buildSubmitPayload: answers failed validation — call validateAll() first (${detail}).`,\n );\n }\n\n // Only keys the active spec defines, with empty optionals omitted.\n const known = knownFieldKeys();\n const answers: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(parsed.data)) {\n if (known.has(key) && value !== undefined && value !== \"\") {\n answers[key] = value;\n }\n }\n const selectedServices = deriveSelectedServices();\n return {\n specVersion,\n answers,\n ...(selectedServices.length > 0 ? { selectedServices } : {}),\n consent: {\n tosAccepted: effective.tosAccepted,\n privacyAccepted: effective.privacyAccepted,\n ...(consentDocuments !== undefined\n ? { documents: consentDocuments }\n : {}),\n } as {\n tosAccepted: true;\n privacyAccepted: true;\n documents?: ConsentSubmitDocument[];\n },\n credentials: {\n email: state.credentials.email,\n ...(state.credentials.displayName\n ? { displayName: state.credentials.displayName }\n : {}),\n },\n organisationName: state.credentials.organisationName,\n subdomain: state.credentials.subdomain,\n };\n },\n\n applyNewSpec(newSpec) {\n steps = newSpec.forms.signup.steps;\n specVersion = newSpec.specVersion;\n\n // Drop answers for fields the new spec no longer defines.\n const known = new Set<string>();\n for (const step of steps) {\n for (const field of step.fields) known.add(field.key);\n }\n const answers: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(state.answers)) {\n if (known.has(key)) answers[key] = value;\n }\n\n // A spec bump may ALSO carry new consent-doc versions — swap the pack so\n // changed docs require re-acceptance. Mark consentStale iff any accepted\n // doc was actually reset. (applyNewPack emits via the subscription; the\n // final state below overwrites consentState with the post-swap value.)\n const resetKeys = swapConsentPack(newSpec);\n\n state = {\n ...state,\n answers,\n stepCount: steps.length,\n specVersion,\n specStale: true,\n status: \"editing\",\n serverError: null,\n consentState: consentController.getState(),\n consentStale: state.consentStale || resetKeys.length > 0,\n staleConsentKeys: resetKeys,\n consentErrors: [],\n };\n state.selectedServices = deriveSelectedServices();\n\n // Reposition to the first step with errors under the NEW schema so\n // the user reviews exactly what changed; errors render immediately.\n const stepIndex = Math.min(firstStepWithErrors(), steps.length - 1);\n const currentStep = steps[Math.max(stepIndex, 0)] ?? null;\n // The repositioned step is being shown with errors → treat it as\n // validated so live-revalidation is active there immediately.\n validatedSteps = new Set<number>([Math.max(stepIndex, 0)]);\n state = {\n ...state,\n stepIndex: Math.max(stepIndex, 0),\n currentStep,\n errors: currentStep ? runStepValidation(currentStep) : [],\n };\n emit();\n },\n\n applyNewConsentPack(newSpec) {\n // Pure consent_stale swap (D543 §4): the form fields are unchanged; only\n // the consent docs may have bumped. Reset acceptance for changed docs\n // (re-acceptance required — NEVER auto-accept), mark consentStale.\n const resetKeys = swapConsentPack(newSpec);\n // Keep specVersion in lockstep — a consent_stale refetch carries the\n // current spec, whose specVersion the next submit must echo.\n specVersion = newSpec.specVersion;\n state = {\n ...state,\n specVersion,\n consentState: consentController.getState(),\n consentStale: true,\n staleConsentKeys: resetKeys,\n consentErrors: [],\n status: \"editing\",\n serverError: null,\n };\n emit();\n },\n\n acknowledgeConsentStale() {\n state = { ...state, consentStale: false, staleConsentKeys: [] };\n emit();\n },\n\n acknowledgeSpecStale() {\n state = { ...state, specStale: false };\n emit();\n },\n\n setSubmitting() {\n state = {\n ...state,\n status: \"submitting\",\n serverError: null,\n };\n emit();\n },\n\n setSuccess(terminalStage) {\n state = { ...state, status: \"success\", terminalStage, serverError: null };\n emit();\n },\n\n setError(message) {\n state = { ...state, status: \"error\", serverError: message };\n emit();\n },\n\n reset() {\n validatedSteps = new Set<number>();\n consentValidated = false;\n // Rebuild the consent controller from the CURRENT (possibly swapped)\n // docs so reset() clears all acceptance/evidence back to pristine. Drop\n // the old subscription and re-subscribe the new instance.\n const currentDocs = consentController\n .getState()\n .documents.map((d) => d.doc);\n unsubscribeConsent();\n consentController = createConsentController(\n currentDocs.length > 0 ? { documents: currentDocs } : undefined,\n );\n unsubscribeConsent = consentController.subscribe(() =>\n syncConsentState(),\n );\n state = {\n stepIndex: 0,\n stepCount: steps.length,\n currentStep: steps[0] ?? null,\n answers: {},\n selectedServices: [],\n errors: [],\n accountErrors: [],\n consent: { tosAccepted: false, privacyAccepted: false },\n credentials: {\n email: \"\",\n displayName: \"\",\n organisationName: \"\",\n subdomain: \"\",\n },\n status: \"editing\",\n serverError: null,\n specStale: false,\n specVersion,\n terminalStage: null,\n consentState: consentController.getState(),\n consentStale: false,\n staleConsentKeys: [],\n consentErrors: [],\n };\n emit();\n },\n\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n"]}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { fetchDocumentContent } from './chunk-SEKNVHD3.js';
|
|
2
|
+
import createDOMPurify from 'dompurify';
|
|
3
|
+
import { marked } from 'marked';
|
|
4
|
+
|
|
5
|
+
var purifier = null;
|
|
6
|
+
function getPurifier() {
|
|
7
|
+
if (purifier) return purifier;
|
|
8
|
+
const win = globalThis.window ?? globalThis;
|
|
9
|
+
purifier = createDOMPurify(win);
|
|
10
|
+
return purifier;
|
|
11
|
+
}
|
|
12
|
+
var SCROLL_END_EPSILON = 2;
|
|
13
|
+
function clearNode(node) {
|
|
14
|
+
while (node.firstChild) node.removeChild(node.firstChild);
|
|
15
|
+
}
|
|
16
|
+
function boxHasContent(box) {
|
|
17
|
+
if ((box.textContent ?? "").trim().length > 0) return true;
|
|
18
|
+
return box.querySelector("canvas") !== null;
|
|
19
|
+
}
|
|
20
|
+
function makeScrollBox(control, consentKey) {
|
|
21
|
+
const box = document.createElement("div");
|
|
22
|
+
box.className = "nodii-onboarding-consent-scrollbox";
|
|
23
|
+
box.setAttribute("tabindex", "0");
|
|
24
|
+
box.setAttribute("role", "region");
|
|
25
|
+
const report = () => {
|
|
26
|
+
if (!boxHasContent(box)) return;
|
|
27
|
+
if (box.scrollHeight <= 0) return;
|
|
28
|
+
const ratio = box.scrollHeight - box.clientHeight <= 0 ? (
|
|
29
|
+
// Content is present AND genuinely fits without scrolling → "at end".
|
|
30
|
+
1
|
|
31
|
+
) : Math.min(
|
|
32
|
+
1,
|
|
33
|
+
(box.scrollTop + box.clientHeight + SCROLL_END_EPSILON) / box.scrollHeight
|
|
34
|
+
);
|
|
35
|
+
control.reportScrollProgress(consentKey, ratio);
|
|
36
|
+
};
|
|
37
|
+
box.addEventListener("scroll", report);
|
|
38
|
+
return { box, reportScroll: report };
|
|
39
|
+
}
|
|
40
|
+
function isMarkdown(fetched, doc) {
|
|
41
|
+
return fetched.contentType.includes("markdown") || /\.mdx?(\?|#|$)/i.test(doc.downloadUrl);
|
|
42
|
+
}
|
|
43
|
+
var DANGEROUS_TAGS = /* @__PURE__ */ new Set([
|
|
44
|
+
"SCRIPT",
|
|
45
|
+
"IFRAME",
|
|
46
|
+
"OBJECT",
|
|
47
|
+
"EMBED",
|
|
48
|
+
"FORM",
|
|
49
|
+
"STYLE",
|
|
50
|
+
"LINK",
|
|
51
|
+
"META",
|
|
52
|
+
"BASE"
|
|
53
|
+
]);
|
|
54
|
+
function normalizeUrlForSchemeCheck(value) {
|
|
55
|
+
let out = "";
|
|
56
|
+
for (let i = 0; i < value.length; i++) {
|
|
57
|
+
const cp = value.charCodeAt(i);
|
|
58
|
+
if (cp > 32 && cp !== 127) out += value[i];
|
|
59
|
+
}
|
|
60
|
+
return out.toLowerCase();
|
|
61
|
+
}
|
|
62
|
+
var DANGEROUS_URL_SCHEMES = ["javascript:", "vbscript:", "data:text/html"];
|
|
63
|
+
function hardenElement(root) {
|
|
64
|
+
const walker = (node) => {
|
|
65
|
+
const children = Array.from(node.children);
|
|
66
|
+
if (DANGEROUS_TAGS.has(node.tagName)) {
|
|
67
|
+
node.remove();
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
for (const attr of Array.from(node.attributes)) {
|
|
71
|
+
const name = attr.name.toLowerCase();
|
|
72
|
+
const value = normalizeUrlForSchemeCheck(attr.value);
|
|
73
|
+
if (name.startsWith("on")) {
|
|
74
|
+
node.removeAttribute(attr.name);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if ((name === "href" || name === "src" || name === "xlink:href") && DANGEROUS_URL_SCHEMES.some((s) => value.startsWith(s))) {
|
|
78
|
+
node.removeAttribute(attr.name);
|
|
79
|
+
}
|
|
80
|
+
if (name === "srcdoc") node.removeAttribute(attr.name);
|
|
81
|
+
}
|
|
82
|
+
for (const child of children) walker(child);
|
|
83
|
+
};
|
|
84
|
+
for (const child of Array.from(root.children)) walker(child);
|
|
85
|
+
}
|
|
86
|
+
function renderSanitizedHtml(container, control, consentKey, html) {
|
|
87
|
+
clearNode(container);
|
|
88
|
+
const { box, reportScroll } = makeScrollBox(control, consentKey);
|
|
89
|
+
const body = document.createElement("div");
|
|
90
|
+
body.className = "nodii-onboarding-consent-doc-body";
|
|
91
|
+
body.innerHTML = getPurifier().sanitize(html, {
|
|
92
|
+
FORBID_TAGS: ["iframe", "object", "embed", "form"],
|
|
93
|
+
FORBID_ATTR: ["srcdoc"],
|
|
94
|
+
ADD_ATTR: ["target", "rel"]
|
|
95
|
+
});
|
|
96
|
+
hardenElement(body);
|
|
97
|
+
box.appendChild(body);
|
|
98
|
+
container.appendChild(box);
|
|
99
|
+
reportScroll();
|
|
100
|
+
}
|
|
101
|
+
function renderPlainText(container, control, consentKey, text) {
|
|
102
|
+
clearNode(container);
|
|
103
|
+
const { box, reportScroll } = makeScrollBox(control, consentKey);
|
|
104
|
+
const body = document.createElement("div");
|
|
105
|
+
body.className = "nodii-onboarding-consent-doc-body";
|
|
106
|
+
body.textContent = text;
|
|
107
|
+
box.appendChild(body);
|
|
108
|
+
container.appendChild(box);
|
|
109
|
+
reportScroll();
|
|
110
|
+
}
|
|
111
|
+
function renderOpenGateAffordance(container, control, consentKey, doc, note) {
|
|
112
|
+
clearNode(container);
|
|
113
|
+
const link = document.createElement("a");
|
|
114
|
+
link.className = "nodii-onboarding-consent-open";
|
|
115
|
+
link.href = doc.downloadUrl;
|
|
116
|
+
link.target = "_blank";
|
|
117
|
+
link.rel = "noopener noreferrer";
|
|
118
|
+
link.textContent = `Open ${doc.title}`;
|
|
119
|
+
const markOpened = () => control.markOpened(consentKey);
|
|
120
|
+
link.addEventListener("click", markOpened);
|
|
121
|
+
link.addEventListener("keydown", (event) => {
|
|
122
|
+
if (event.key === "Enter") markOpened();
|
|
123
|
+
});
|
|
124
|
+
const row = document.createElement("div");
|
|
125
|
+
row.className = "nodii-onboarding-consent-open-row";
|
|
126
|
+
row.appendChild(link);
|
|
127
|
+
if (note) {
|
|
128
|
+
const noteEl = document.createElement("p");
|
|
129
|
+
noteEl.className = "nodii-onboarding-consent-note";
|
|
130
|
+
noteEl.textContent = note;
|
|
131
|
+
row.appendChild(noteEl);
|
|
132
|
+
}
|
|
133
|
+
container.appendChild(row);
|
|
134
|
+
}
|
|
135
|
+
function renderUnrenderableError(container, doc, onRetry) {
|
|
136
|
+
clearNode(container);
|
|
137
|
+
const wrap = document.createElement("div");
|
|
138
|
+
wrap.className = "nodii-onboarding-consent-unrenderable";
|
|
139
|
+
wrap.setAttribute("role", "alert");
|
|
140
|
+
const msg = document.createElement("p");
|
|
141
|
+
msg.className = "nodii-onboarding-consent-error";
|
|
142
|
+
msg.textContent = `\u201C${doc.title}\u201D could not be loaded, so it cannot be accepted yet. Please retry; if it keeps failing, contact support.`;
|
|
143
|
+
wrap.appendChild(msg);
|
|
144
|
+
const retry = document.createElement("button");
|
|
145
|
+
retry.type = "button";
|
|
146
|
+
retry.className = "nodii-onboarding-consent-retry";
|
|
147
|
+
retry.textContent = "Retry loading document";
|
|
148
|
+
retry.addEventListener("click", onRetry);
|
|
149
|
+
wrap.appendChild(retry);
|
|
150
|
+
const link = document.createElement("a");
|
|
151
|
+
link.className = "nodii-onboarding-consent-open";
|
|
152
|
+
link.href = doc.downloadUrl;
|
|
153
|
+
link.target = "_blank";
|
|
154
|
+
link.rel = "noopener noreferrer";
|
|
155
|
+
link.textContent = `Open ${doc.title} in a new tab`;
|
|
156
|
+
wrap.appendChild(link);
|
|
157
|
+
container.appendChild(wrap);
|
|
158
|
+
}
|
|
159
|
+
async function renderPdf(container, control, consentKey, doc, blob, onRetry) {
|
|
160
|
+
const fail = () => handleRenderFailure(container, control, consentKey, doc, onRetry);
|
|
161
|
+
let pdfjs;
|
|
162
|
+
try {
|
|
163
|
+
pdfjs = await import('pdfjs-dist');
|
|
164
|
+
} catch {
|
|
165
|
+
return fail();
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
configurePdfWorker(pdfjs);
|
|
169
|
+
const data = new Uint8Array(await blob.arrayBuffer());
|
|
170
|
+
const pdf = await pdfjs.getDocument({ data }).promise;
|
|
171
|
+
const body = document.createElement("div");
|
|
172
|
+
body.className = "nodii-onboarding-consent-doc-body nodii-consent-pdf";
|
|
173
|
+
for (let pageNo = 1; pageNo <= pdf.numPages; pageNo++) {
|
|
174
|
+
const page = await pdf.getPage(pageNo);
|
|
175
|
+
const viewport = page.getViewport({ scale: 1.2 });
|
|
176
|
+
const canvas = document.createElement("canvas");
|
|
177
|
+
canvas.className = "nodii-consent-pdf-page";
|
|
178
|
+
canvas.width = Math.ceil(viewport.width);
|
|
179
|
+
canvas.height = Math.ceil(viewport.height);
|
|
180
|
+
const ctx = canvas.getContext("2d");
|
|
181
|
+
if (ctx) {
|
|
182
|
+
await page.render({ canvas, canvasContext: ctx, viewport }).promise;
|
|
183
|
+
}
|
|
184
|
+
body.appendChild(canvas);
|
|
185
|
+
}
|
|
186
|
+
if (typeof container.isConnected === "boolean" && !container.isConnected) {
|
|
187
|
+
return { renderedAs: "unrenderable" };
|
|
188
|
+
}
|
|
189
|
+
if (body.childElementCount === 0) return fail();
|
|
190
|
+
clearNode(container);
|
|
191
|
+
const { box, reportScroll } = makeScrollBox(control, consentKey);
|
|
192
|
+
box.appendChild(body);
|
|
193
|
+
container.appendChild(box);
|
|
194
|
+
reportScroll();
|
|
195
|
+
return { renderedAs: "pdf" };
|
|
196
|
+
} catch {
|
|
197
|
+
return fail();
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
var pdfWorkerConfigured = false;
|
|
201
|
+
function resolvePackagedWorkerUrl() {
|
|
202
|
+
const WORKER_SPEC = "pdfjs-dist/build/pdf.worker.min.mjs";
|
|
203
|
+
const meta = import.meta;
|
|
204
|
+
if (typeof meta.resolve === "function") {
|
|
205
|
+
try {
|
|
206
|
+
const resolved = meta.resolve(WORKER_SPEC);
|
|
207
|
+
if (resolved) return resolved;
|
|
208
|
+
} catch {
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
try {
|
|
212
|
+
return new URL(WORKER_SPEC, import.meta.url).href;
|
|
213
|
+
} catch {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function configurePdfWorker(pdfjs) {
|
|
218
|
+
if (pdfWorkerConfigured) return;
|
|
219
|
+
const opts = pdfjs.GlobalWorkerOptions;
|
|
220
|
+
if (opts.workerPort || opts.workerSrc) {
|
|
221
|
+
pdfWorkerConfigured = true;
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const packagedUrl = resolvePackagedWorkerUrl();
|
|
225
|
+
if (packagedUrl) {
|
|
226
|
+
opts.workerSrc = packagedUrl;
|
|
227
|
+
} else {
|
|
228
|
+
const version = pdfjs.version ?? "";
|
|
229
|
+
opts.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${version}/build/pdf.worker.min.mjs`;
|
|
230
|
+
}
|
|
231
|
+
pdfWorkerConfigured = true;
|
|
232
|
+
}
|
|
233
|
+
function handleRenderFailure(container, control, consentKey, doc, onRetry) {
|
|
234
|
+
if (doc.acceptanceLevel === "open_then_accept") {
|
|
235
|
+
renderOpenGateAffordance(
|
|
236
|
+
container,
|
|
237
|
+
control,
|
|
238
|
+
consentKey,
|
|
239
|
+
doc,
|
|
240
|
+
"The inline preview is unavailable. Opening the document in a new tab satisfies this step."
|
|
241
|
+
);
|
|
242
|
+
return { renderedAs: "open-affordance" };
|
|
243
|
+
}
|
|
244
|
+
renderUnrenderableError(container, doc, onRetry);
|
|
245
|
+
return { renderedAs: "unrenderable" };
|
|
246
|
+
}
|
|
247
|
+
async function renderConsentDocument(container, doc, control, options) {
|
|
248
|
+
const { consentKey } = options;
|
|
249
|
+
const onRetry = () => {
|
|
250
|
+
void renderConsentDocument(container, doc, control, options);
|
|
251
|
+
};
|
|
252
|
+
let fetched;
|
|
253
|
+
try {
|
|
254
|
+
fetched = await fetchDocumentContent(doc, {
|
|
255
|
+
fetch: options.fetch,
|
|
256
|
+
timeoutMs: options.timeoutMs
|
|
257
|
+
});
|
|
258
|
+
} catch {
|
|
259
|
+
return handleRenderFailure(container, control, consentKey, doc, onRetry);
|
|
260
|
+
}
|
|
261
|
+
if (typeof container.isConnected === "boolean" && !container.isConnected) {
|
|
262
|
+
return { renderedAs: "unrenderable" };
|
|
263
|
+
}
|
|
264
|
+
if (doc.acceptanceLevel === "open_then_accept") {
|
|
265
|
+
renderOpenGateAffordance(
|
|
266
|
+
container,
|
|
267
|
+
control,
|
|
268
|
+
consentKey,
|
|
269
|
+
doc,
|
|
270
|
+
"Open the document in a new tab to review it \u2014 that satisfies this step."
|
|
271
|
+
);
|
|
272
|
+
return { renderedAs: "open-affordance" };
|
|
273
|
+
}
|
|
274
|
+
if (fetched.kind === "pdf" && fetched.blob) {
|
|
275
|
+
return renderPdf(
|
|
276
|
+
container,
|
|
277
|
+
control,
|
|
278
|
+
consentKey,
|
|
279
|
+
doc,
|
|
280
|
+
fetched.blob,
|
|
281
|
+
onRetry
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
if (fetched.kind === "binary") {
|
|
285
|
+
return handleRenderFailure(container, control, consentKey, doc, onRetry);
|
|
286
|
+
}
|
|
287
|
+
const text = fetched.text ?? "";
|
|
288
|
+
if (isMarkdown(fetched, doc)) {
|
|
289
|
+
const html = await marked.parse(text, { async: true });
|
|
290
|
+
renderSanitizedHtml(container, control, consentKey, html);
|
|
291
|
+
return { renderedAs: "markdown" };
|
|
292
|
+
}
|
|
293
|
+
if (fetched.kind === "html") {
|
|
294
|
+
renderSanitizedHtml(container, control, consentKey, text);
|
|
295
|
+
return { renderedAs: "html" };
|
|
296
|
+
}
|
|
297
|
+
renderPlainText(container, control, consentKey, text);
|
|
298
|
+
return { renderedAs: "text" };
|
|
299
|
+
}
|
|
300
|
+
function _resetPdfWorkerState() {
|
|
301
|
+
pdfWorkerConfigured = false;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export { _resetPdfWorkerState, renderConsentDocument };
|
|
305
|
+
//# sourceMappingURL=chunk-LVJM4CTG.js.map
|
|
306
|
+
//# sourceMappingURL=chunk-LVJM4CTG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/viewer/render.ts"],"names":[],"mappings":"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","file":"chunk-LVJM4CTG.js","sourcesContent":["/**\n * Default ConsentPack document viewer (D543 §5) — @nodii/onboarding/viewer.\n *\n * A SEPARATE, opt-in module built on STANDARD libraries so the base SDK stays\n * lean: consumers only pay for the viewer if they render our default consent\n * components. The headless controller (@nodii/onboarding/consent) knows nothing\n * about this — it just receives reportScrollProgress / markScrolledToEnd /\n * markOpened from whatever renders the doc.\n *\n * Renderers (per fetched artifact — NO IFRAME anywhere; everything is inline,\n * same-origin, so `scroll_then_accept` scroll tracking is REAL):\n * - text/html → sanitize with DOMPurify, inject into a scroll <div>.\n * - markdown → marked → DOMPurify → inject into a scroll <div>.\n * - text/plain → escaped text (textContent) in a scroll <div>.\n * - application/pdf → PDF.js (pdfjs-dist), rendered to <canvas> + a text\n * layer, page by page, in a scroll <div>. PDF.js is LAZY-loaded via a\n * dynamic import() ONLY when a PDF doc is actually present, so it never\n * bloats the base bundle.\n *\n * The scroll container's scroll-to-end (and the PDF/open fallbacks) drive the\n * consent controller so the gate works for real. A failed fetch/render\n * degrades to an \"open in a new tab\" affordance (marks the doc opened /\n * scrolled) so every doc stays consentable.\n *\n * Bundle discipline: DOMPurify + marked are imported at module top (this is\n * the VIEWER entry, not the base SDK — the base `@nodii/onboarding` never\n * statically imports this file). pdfjs-dist is imported ONLY via dynamic\n * import() inside renderPdf, so even the viewer entry doesn't eagerly load it.\n */\n\nimport createDOMPurify from \"dompurify\";\nimport { marked } from \"marked\";\nimport type { ConsentController } from \"../consent/controller.js\";\nimport type { ConsentDocument } from \"../consent/model.js\";\nimport {\n fetchDocumentContent,\n type FetchedConsentDocument,\n} from \"../consent/document.js\";\n\n/**\n * DOMPurify bound to the current window. The default import is BOTH a\n * pre-bound instance AND a factory `(window) => instance`. Binding it\n * explicitly to `globalThis` (which happy-dom / a real browser populate with\n * `window`) guarantees a working DOM even in environments where DOMPurify's\n * implicit global detection misfires (e.g. bun + happy-dom under test), where\n * an unbound instance silently passes HTML through UN-sanitized. Lazily\n * memoized so we only bind once.\n */\nlet purifier: ReturnType<typeof createDOMPurify> | null = null;\nfunction getPurifier(): ReturnType<typeof createDOMPurify> {\n if (purifier) return purifier;\n const win = (globalThis as { window?: unknown }).window ?? globalThis;\n // createDOMPurify is callable as a factory; when the arg is a window-like\n // object it returns an instance bound to it.\n purifier = (\n createDOMPurify as unknown as (\n w: unknown,\n ) => ReturnType<typeof createDOMPurify>\n )(win);\n return purifier;\n}\n\nexport interface ConsentDocumentViewerOptions {\n /** Injectable fetch for the presigned artifact GET (defaults to global). */\n fetch?: typeof globalThis.fetch;\n /** Per-request timeout in ms (default from fetchDocumentContent). */\n timeoutMs?: number;\n /**\n * The `key` the controller identifies this document by (doc_type |\n * custom:<key>). The viewer reports scroll/open evidence under this key.\n */\n consentKey: string;\n}\n\n/** Result of rendering — lets the caller know how the doc was displayed. */\nexport interface ConsentDocumentViewerResult {\n /**\n * How the artifact was rendered.\n *\n * - html | markdown | text | pdf → rendered inline (gate is driven by real\n * scroll/open).\n * - open-affordance → an `open_then_accept` doc that opens in a new tab (the\n * real-open IS its gate; satisfies ONLY `opened`).\n * - unrenderable → a GATED doc (scroll_then_accept) that could NOT be\n * rendered inline. The gate stays UNSATISFIABLE — accept is disabled and a\n * clear error is shown. NO evidence is ever fabricated (COMPLIANCE, D543).\n */\n renderedAs:\n \"html\" | \"markdown\" | \"text\" | \"pdf\" | \"open-affordance\" | \"unrenderable\";\n}\n\nconst SCROLL_END_EPSILON = 2;\n\nfunction clearNode(node: HTMLElement): void {\n while (node.firstChild) node.removeChild(node.firstChild);\n}\n\n/**\n * Does the box hold ACTUAL readable rendered content? A \"content fits without\n * scrolling\" ratio of 1 is only legitimate when there is genuinely something to\n * have read. Content = non-empty text (HTML/markdown/text render) OR at least\n * one rendered PDF page canvas. A bare wrapper `<div>` with empty text is NOT\n * content — so an empty-artifact doc (e.g. a 0-byte or all-whitespace body, or\n * a not-yet-populated box) can NEVER satisfy the gate. This is the P0a\n * by-construction guarantee: the ratio-1 branch depends on rendered-content\n * presence, not on geometry a headless runtime cannot measure — fabrication is\n * impossible in EVERY runtime.\n */\nfunction boxHasContent(box: HTMLElement): boolean {\n if ((box.textContent ?? \"\").trim().length > 0) return true;\n // PDF pages carry no text — a rendered page canvas counts as content.\n return box.querySelector(\"canvas\") !== null;\n}\n\n/**\n * A scroll <div> that reports scroll progress to the controller. Returns the\n * box AND a `reportScroll` fn the caller MUST invoke ONLY AFTER real content is\n * appended — never at creation. `report` refuses to satisfy the \"fits without\n * scrolling\" case unless the box actually holds content, so an empty or\n * pre-render box can never latch scrolled_to_end (P0a — by construction).\n */\nfunction makeScrollBox(\n control: ConsentController,\n consentKey: string,\n): { box: HTMLDivElement; reportScroll: () => void } {\n const box = document.createElement(\"div\");\n box.className = \"nodii-onboarding-consent-scrollbox\";\n box.setAttribute(\"tabindex\", \"0\");\n box.setAttribute(\"role\", \"region\");\n const report = (): void => {\n // COMPLIANCE (P0a): an empty / not-yet-rendered box can NEVER satisfy the\n // gate — there is nothing to have read. This holds in EVERY runtime,\n // independent of scroll geometry (which a headless DOM cannot measure).\n if (!boxHasContent(box)) return;\n // Unmeasured container (no layout yet / happy-dom) → do NOT report a\n // fits-without-scroll: scrollHeight 0 is not evidence the user reached the\n // end. A real scroll event still reports its measured ratio.\n if (box.scrollHeight <= 0) return;\n const ratio =\n box.scrollHeight - box.clientHeight <= 0\n ? // Content is present AND genuinely fits without scrolling → \"at end\".\n 1\n : Math.min(\n 1,\n (box.scrollTop + box.clientHeight + SCROLL_END_EPSILON) /\n box.scrollHeight,\n );\n control.reportScrollProgress(consentKey, ratio);\n };\n box.addEventListener(\"scroll\", report);\n // NOTE: no report is scheduled at creation. The caller invokes reportScroll()\n // AFTER content is appended (short-doc auto-unlock then only fires with\n // content present). This is what makes P0a a construction guarantee.\n return { box, reportScroll: report };\n}\n\n/** Detect markdown by content-type or a .md-looking downloadUrl. */\nfunction isMarkdown(\n fetched: FetchedConsentDocument,\n doc: Pick<ConsentDocument, \"downloadUrl\">,\n): boolean {\n return (\n fetched.contentType.includes(\"markdown\") ||\n /\\.mdx?(\\?|#|$)/i.test(doc.downloadUrl)\n );\n}\n\n/** Tags that must never survive into the rendered consent document. */\nconst DANGEROUS_TAGS = new Set([\n \"SCRIPT\",\n \"IFRAME\",\n \"OBJECT\",\n \"EMBED\",\n \"FORM\",\n \"STYLE\",\n \"LINK\",\n \"META\",\n \"BASE\",\n]);\n\n/**\n * Defense-in-depth pass AFTER DOMPurify: walk the parsed DOM and remove any\n * dangerous element, every on* event-handler attribute, and javascript:/data:\n * URLs. DOMPurify is the primary, audited sanitizer, but this deterministic\n * DOM walk (a) hardens against any DOMPurify config gap and (b) is provably\n * correct in EVERY runtime — including ones where DOMPurify's own DOM-based\n * pass is a no-op (e.g. certain SSR/test DOMs). Belt-and-suspenders, not a\n * hand-rolled replacement for DOMPurify.\n */\n/**\n * Normalize a URL for scheme inspection the way a browser does BEFORE\n * resolving it: strip ALL ASCII whitespace and control characters (code\n * points <= 0x20, plus DEL 0x7F) anywhere in the string, not just the ends.\n * Browsers ignore these inside a URL, so a scheme split by an embedded tab/\n * newline/NUL (e.g. jav<TAB>ascript:) still executes; a mere .trim() leaves\n * the embedded ones and the startsWith('javascript:') check is bypassed.\n * Char-code filtering avoids embedding literal control bytes in a regex.\n */\nfunction normalizeUrlForSchemeCheck(value: string): string {\n let out = \"\";\n for (let i = 0; i < value.length; i++) {\n const cp = value.charCodeAt(i);\n if (cp > 0x20 && cp !== 0x7f) out += value[i];\n }\n return out.toLowerCase();\n}\n\nconst DANGEROUS_URL_SCHEMES = [\"javascript:\", \"vbscript:\", \"data:text/html\"];\n\nfunction hardenElement(root: HTMLElement): void {\n const walker = (node: Element): void => {\n // Copy children first — removal mutates the live list.\n const children = Array.from(node.children);\n if (DANGEROUS_TAGS.has(node.tagName)) {\n node.remove();\n return;\n }\n for (const attr of Array.from(node.attributes)) {\n const name = attr.name.toLowerCase();\n // Whitespace/control-stripped, lower-cased value for scheme inspection.\n const value = normalizeUrlForSchemeCheck(attr.value);\n if (name.startsWith(\"on\")) {\n node.removeAttribute(attr.name);\n continue;\n }\n if (\n (name === \"href\" || name === \"src\" || name === \"xlink:href\") &&\n DANGEROUS_URL_SCHEMES.some((s) => value.startsWith(s))\n ) {\n node.removeAttribute(attr.name);\n }\n if (name === \"srcdoc\") node.removeAttribute(attr.name);\n }\n for (const child of children) walker(child);\n };\n for (const child of Array.from(root.children)) walker(child);\n}\n\n/** Render sanitized HTML inline into a scroll box. */\nfunction renderSanitizedHtml(\n container: HTMLElement,\n control: ConsentController,\n consentKey: string,\n html: string,\n): void {\n clearNode(container);\n const { box, reportScroll } = makeScrollBox(control, consentKey);\n const body = document.createElement(\"div\");\n body.className = \"nodii-onboarding-consent-doc-body\";\n // Primary: DOMPurify (the standard, audited Cure53 sanitizer). FORBID_TAGS\n // on <iframe>/<object>/<embed>/<form> so a doc can't smuggle a frame in.\n body.innerHTML = getPurifier().sanitize(html, {\n FORBID_TAGS: [\"iframe\", \"object\", \"embed\", \"form\"],\n FORBID_ATTR: [\"srcdoc\"],\n ADD_ATTR: [\"target\", \"rel\"],\n });\n // Defense-in-depth: a deterministic DOM walk that removes any residual\n // dangerous node/attr, correct in every runtime (see hardenElement).\n hardenElement(body);\n box.appendChild(body);\n container.appendChild(box);\n // Content is now IN the box → the short-doc auto-unlock may fire (P0a: report\n // ONLY after content is present, never at box creation).\n reportScroll();\n}\n\n/** Render escaped plain text inline into a scroll box. */\nfunction renderPlainText(\n container: HTMLElement,\n control: ConsentController,\n consentKey: string,\n text: string,\n): void {\n clearNode(container);\n const { box, reportScroll } = makeScrollBox(control, consentKey);\n const body = document.createElement(\"div\");\n body.className = \"nodii-onboarding-consent-doc-body\";\n body.textContent = text; // safe-by-construction (no markup interpretation)\n box.appendChild(body);\n container.appendChild(box);\n reportScroll(); // only after content is present (P0a)\n}\n\n/**\n * The LEGITIMATE gate affordance for an `open_then_accept` doc: an open-in-new\n * tab link. Opening the doc in a new tab IS the gate for this level, so a REAL\n * navigation satisfies ONLY `opened` (never `scrolled_to_end`). A native\n * <a target=\"_blank\"> navigates on click AND on Enter (keyboard activation of\n * an anchor) — we mark `opened` on those, which correspond to a real open. We\n * do NOT bind Space (Space does not activate an anchor → no navigation → no\n * open → must not mark opened; binding it would fabricate evidence).\n *\n * This is used both as the primary affordance for open_then_accept and as the\n * failure fallback for open_then_accept when inline preview is unavailable —\n * either way the gate is genuinely the real open.\n */\nfunction renderOpenGateAffordance(\n container: HTMLElement,\n control: ConsentController,\n consentKey: string,\n doc: Pick<ConsentDocument, \"downloadUrl\" | \"title\">,\n note?: string,\n): void {\n clearNode(container);\n const link = document.createElement(\"a\");\n link.className = \"nodii-onboarding-consent-open\";\n link.href = doc.downloadUrl;\n link.target = \"_blank\";\n link.rel = \"noopener noreferrer\";\n link.textContent = `Open ${doc.title}`;\n // Mark opened ONLY on real activation of the anchor (click / Enter). No\n // Space handler — Space does not navigate an <a>, so it is not a real open.\n const markOpened = (): void => control.markOpened(consentKey);\n link.addEventListener(\"click\", markOpened);\n link.addEventListener(\"keydown\", (event) => {\n if ((event as KeyboardEvent).key === \"Enter\") markOpened();\n });\n const row = document.createElement(\"div\");\n row.className = \"nodii-onboarding-consent-open-row\";\n row.appendChild(link);\n if (note) {\n const noteEl = document.createElement(\"p\");\n noteEl.className = \"nodii-onboarding-consent-note\";\n noteEl.textContent = note;\n row.appendChild(noteEl);\n }\n container.appendChild(row);\n}\n\n/**\n * COMPLIANCE-CRITICAL (P0, D543): a GATED doc whose acceptance requires SEEING\n * the content inline (scroll_then_accept) could NOT be rendered inline (fetch\n * failure, expired presigned URL, CORS, octet-stream, PDF.js failure, viewer\n * unavailable). The gate MUST stay UNSATISFIABLE — the SDK NEVER fabricates\n * `scrolled_to_end` on a mere click. Render a clear error + a Retry, and an\n * \"Open in a new tab\" link that is INFORMATIONAL ONLY (it does NOT satisfy the\n * scroll gate — reading in a new tab is not evidence the user scrolled the\n * rendered doc to the end for this level). Accept stays disabled; the operator\n * must fix the artifact/URL for this doc to become acceptable.\n */\nfunction renderUnrenderableError(\n container: HTMLElement,\n doc: Pick<ConsentDocument, \"downloadUrl\" | \"title\">,\n onRetry: () => void,\n): void {\n clearNode(container);\n const wrap = document.createElement(\"div\");\n wrap.className = \"nodii-onboarding-consent-unrenderable\";\n wrap.setAttribute(\"role\", \"alert\");\n\n const msg = document.createElement(\"p\");\n msg.className = \"nodii-onboarding-consent-error\";\n msg.textContent = `“${doc.title}” could not be loaded, so it cannot be accepted yet. Please retry; if it keeps failing, contact support.`;\n wrap.appendChild(msg);\n\n const retry = document.createElement(\"button\");\n retry.type = \"button\";\n retry.className = \"nodii-onboarding-consent-retry\";\n retry.textContent = \"Retry loading document\";\n retry.addEventListener(\"click\", onRetry);\n wrap.appendChild(retry);\n\n // Informational only — opening in a new tab does NOT satisfy the scroll gate.\n const link = document.createElement(\"a\");\n link.className = \"nodii-onboarding-consent-open\";\n link.href = doc.downloadUrl;\n link.target = \"_blank\";\n link.rel = \"noopener noreferrer\";\n link.textContent = `Open ${doc.title} in a new tab`;\n wrap.appendChild(link);\n\n container.appendChild(wrap);\n}\n\n/**\n * Render a PDF via PDF.js into a scroll box (canvas per page). pdfjs-dist is\n * LAZY-loaded here (dynamic import) so it never enters the base bundle. On any\n * failure (import/worker/CSP/parse/zero-page), route through handleRenderFailure\n * — for a scroll_then_accept doc that is UNRENDERABLE (gate stays unsatisfiable,\n * never fabricated); for open_then_accept it is the real-open affordance (P0).\n * The scroll box is only attached (and progress only reported) AFTER pages are\n * rendered, so an empty/pre-render box can never satisfy the gate (P0a).\n */\nasync function renderPdf(\n container: HTMLElement,\n control: ConsentController,\n consentKey: string,\n doc: ConsentDocument,\n blob: Blob,\n onRetry: () => void,\n): Promise<ConsentDocumentViewerResult> {\n const fail = (): ConsentDocumentViewerResult =>\n handleRenderFailure(container, control, consentKey, doc, onRetry);\n\n let pdfjs: typeof import(\"pdfjs-dist\");\n try {\n pdfjs = await import(\"pdfjs-dist\");\n } catch {\n return fail();\n }\n\n try {\n // Configure the worker so getDocument does not reject on\n // \"No GlobalWorkerOptions.workerSrc specified\" (pdfjs-dist v6). Resolve the\n // packaged worker via a bundler-friendly URL; if that fails, fall back to\n // the CDN for the exact installed version (never leaves the worker unset).\n configurePdfWorker(pdfjs);\n const data = new Uint8Array(await blob.arrayBuffer());\n const pdf = await pdfjs.getDocument({ data }).promise;\n\n // Render EVERY page into a DETACHED body FIRST — the scroll box is not put\n // into the container (and reportScroll is not called) until real content is\n // present (P0a: an empty/pre-render box can never satisfy the gate, even in\n // a real browser where an empty 360px box measures scrollHeight==clientH).\n const body = document.createElement(\"div\");\n body.className = \"nodii-onboarding-consent-doc-body nodii-consent-pdf\";\n for (let pageNo = 1; pageNo <= pdf.numPages; pageNo++) {\n const page = await pdf.getPage(pageNo);\n const viewport = page.getViewport({ scale: 1.2 });\n const canvas = document.createElement(\"canvas\");\n canvas.className = \"nodii-consent-pdf-page\";\n canvas.width = Math.ceil(viewport.width);\n canvas.height = Math.ceil(viewport.height);\n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n await page.render({ canvas, canvasContext: ctx, viewport }).promise;\n }\n body.appendChild(canvas);\n }\n\n // Lifecycle guard: if the container was detached while we awaited the PDF\n // (stage re-render / unmount / a Retry started a fresh render), abandon —\n // don't mutate an orphaned tree or fight a concurrent render (P2 lifecycle).\n if (typeof container.isConnected === \"boolean\" && !container.isConnected) {\n return { renderedAs: \"unrenderable\" };\n }\n // A zero-page or all-empty PDF has no readable content → treat as a render\n // failure (never satisfy a gate on an empty box).\n if (body.childElementCount === 0) return fail();\n\n clearNode(container);\n const { box, reportScroll } = makeScrollBox(control, consentKey);\n box.appendChild(body);\n container.appendChild(box);\n // Content is now present → the short-PDF auto-unlock may fire (P0a).\n reportScroll();\n return { renderedAs: \"pdf\" };\n } catch {\n return fail();\n }\n}\n\n/** Whether pdfjs already has a worker configured this session. */\nlet pdfWorkerConfigured = false;\n\ninterface WorkerGlobalOptions {\n workerSrc?: string;\n workerPort?: unknown;\n}\n\n/**\n * Resolve the packaged pdf worker module to a LOADABLE URL, robust across\n * runtimes:\n * 1. `import.meta.resolve(...)` — real module resolution (Node/bun ESM);\n * resolves through node_modules to the actual file (the plain\n * `new URL(spec, import.meta.url)` does NOT — it's relative to THIS file,\n * which 404s, the exact P2 dead-fallback bug).\n * 2. `new URL(\"pdfjs-dist/build/pdf.worker.min.mjs\", import.meta.url)` — a\n * bundler (Vite/webpack/tsup) rewrites this to the emitted asset URL.\n * Returns null if neither yields a URL (→ caller falls back to the CDN).\n */\nfunction resolvePackagedWorkerUrl(): string | null {\n const WORKER_SPEC = \"pdfjs-dist/build/pdf.worker.min.mjs\";\n const meta = import.meta as ImportMeta & {\n resolve?: (spec: string) => string;\n };\n if (typeof meta.resolve === \"function\") {\n try {\n const resolved = meta.resolve(WORKER_SPEC);\n if (resolved) return resolved;\n } catch {\n // fall through to the bundler-rewrite form\n }\n }\n try {\n return new URL(WORKER_SPEC, import.meta.url).href;\n } catch {\n return null;\n }\n}\n\n/**\n * Ensure pdfjs has a LOADABLE worker before getDocument (P2). Real pdfjs-dist\n * v6 rejects getDocument without one, and merely SETTING `workerSrc` is not the\n * same as the worker LOADING: the naive `new URL('pdfjs-dist/build/...',\n * import.meta.url)` resolves RELATIVE TO THIS MODULE (not through\n * node_modules), so it points at a path that 404s at load — the dead-fallback\n * bug P2 flags. We resolve the worker to a genuinely-loadable URL instead\n * (`import.meta.resolve` → real module resolution; else the bundler-rewrite\n * `new URL` form; else the version-pinned CDN).\n *\n * We set `workerSrc` (not `workerPort`): a resolved file/asset/CDN URL loads in\n * BOTH a real browser (bundler-served or CDN) AND Node/bun (resolved file\n * path) — proven by the [P2] real-pdfjs test which renders a real PDF with the\n * worker configured here and NO pre-set workerSrc. If the worker still can't\n * load (offline + unresolvable), getDocument rejects and the caller degrades\n * to `unrenderable` — a gated PDF that can't render stays unacceptable, NEVER\n * fabricated (P0). Idempotent per session.\n */\nfunction configurePdfWorker(pdfjs: typeof import(\"pdfjs-dist\")): void {\n if (pdfWorkerConfigured) return;\n const opts = pdfjs.GlobalWorkerOptions as WorkerGlobalOptions;\n // A consumer (or a prior call) already wired a worker → respect it.\n if (opts.workerPort || opts.workerSrc) {\n pdfWorkerConfigured = true;\n return;\n }\n\n const packagedUrl = resolvePackagedWorkerUrl();\n if (packagedUrl) {\n opts.workerSrc = packagedUrl;\n } else {\n // Last resort: version-pinned CDN so a build that can't resolve the asset\n // still gets a real worker rather than silently failing every PDF.\n const version = (pdfjs as { version?: string }).version ?? \"\";\n opts.workerSrc = `https://cdn.jsdelivr.net/npm/pdfjs-dist@${version}/build/pdf.worker.min.mjs`;\n }\n pdfWorkerConfigured = true;\n}\n\n/**\n * COMPLIANCE-CRITICAL failure router (P0): a doc could not be rendered inline.\n * - open_then_accept → the real-open affordance (opening IS its gate; satisfies\n * ONLY `opened`). This is legitimate, not a fabrication.\n * - scroll_then_accept → UNRENDERABLE: the gate stays unsatisfiable, a clear\n * error + Retry is shown, accept is disabled. NEVER fabricate scrolled_to_end.\n * - checkbox → no gate (already satisfiable): show the error + a plain open link\n * for reference; accept remains enabled (the checkbox gate needs no evidence).\n */\nfunction handleRenderFailure(\n container: HTMLElement,\n control: ConsentController,\n consentKey: string,\n doc: ConsentDocument,\n onRetry: () => void,\n): ConsentDocumentViewerResult {\n if (doc.acceptanceLevel === \"open_then_accept\") {\n renderOpenGateAffordance(\n container,\n control,\n consentKey,\n doc,\n \"The inline preview is unavailable. Opening the document in a new tab satisfies this step.\",\n );\n return { renderedAs: \"open-affordance\" };\n }\n // scroll_then_accept (and checkbox — harmless there): show the error. For a\n // scroll gate this leaves it UNSATISFIABLE (accept stays disabled).\n renderUnrenderableError(container, doc, onRetry);\n return { renderedAs: \"unrenderable\" };\n}\n\n/**\n * Fetch + render a consent document INLINE into `container`, wiring its scroll\n * container (or the legitimate open-affordance) to the consent controller so\n * `scroll_then_accept` / `open_then_accept` gates work for real. NO iframe.\n *\n * On ANY inline-render failure for a `scroll_then_accept` doc the gate stays\n * UNSATISFIABLE (never fabricates scrolled_to_end, D543 §5 COMPLIANCE) — the\n * caller's Retry re-invokes this.\n *\n * @returns how the doc was rendered (for the caller's telemetry/UX).\n */\nexport async function renderConsentDocument(\n container: HTMLElement,\n doc: ConsentDocument,\n control: ConsentController,\n options: ConsentDocumentViewerOptions,\n): Promise<ConsentDocumentViewerResult> {\n const { consentKey } = options;\n const onRetry = (): void => {\n void renderConsentDocument(container, doc, control, options);\n };\n\n let fetched: FetchedConsentDocument;\n try {\n fetched = await fetchDocumentContent(doc, {\n fetch: options.fetch,\n timeoutMs: options.timeoutMs,\n });\n } catch {\n return handleRenderFailure(container, control, consentKey, doc, onRetry);\n }\n\n // If the container was detached while we awaited the fetch (the consent stage\n // re-rendered, or the widget unmounted), skip DOM work — a stale render must\n // not mutate an orphaned node or leak an unhandled error.\n if (typeof container.isConnected === \"boolean\" && !container.isConnected) {\n return { renderedAs: \"unrenderable\" };\n }\n\n // open_then_accept: opening the doc in a new tab IS the gate — scrolling an\n // inline render does NOT satisfy it (reportScrollProgress no-ops for this\n // level). So on a SUCCESSFUL fetch we ALSO present the open affordance (which\n // marks `opened` on a real open) so the gate is satisfiable through the\n // default viewer (P1). We do not attempt an inline scroll gate here.\n if (doc.acceptanceLevel === \"open_then_accept\") {\n renderOpenGateAffordance(\n container,\n control,\n consentKey,\n doc,\n \"Open the document in a new tab to review it — that satisfies this step.\",\n );\n return { renderedAs: \"open-affordance\" };\n }\n\n if (fetched.kind === \"pdf\" && fetched.blob) {\n return renderPdf(\n container,\n control,\n consentKey,\n doc,\n fetched.blob,\n onRetry,\n );\n }\n if (fetched.kind === \"binary\") {\n // A binary/octet-stream artifact cannot be previewed inline → same\n // compliance rule: gated docs stay unsatisfiable, never click-to-satisfy.\n return handleRenderFailure(container, control, consentKey, doc, onRetry);\n }\n // text or html\n const text = fetched.text ?? \"\";\n if (isMarkdown(fetched, doc)) {\n const html = await marked.parse(text, { async: true });\n renderSanitizedHtml(container, control, consentKey, html);\n return { renderedAs: \"markdown\" };\n }\n if (fetched.kind === \"html\") {\n renderSanitizedHtml(container, control, consentKey, text);\n return { renderedAs: \"html\" };\n }\n renderPlainText(container, control, consentKey, text);\n return { renderedAs: \"text\" };\n}\n\n/** Reset the module-level pdf-worker latch (tests). */\nexport function _resetPdfWorkerState(): void {\n pdfWorkerConfigured = false;\n}\n"]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { OnboardingError, DEFAULT_REQUEST_TIMEOUT_MS, fetchWithTimeout } from './chunk-XJTJPBJB.js';
|
|
2
|
+
|
|
3
|
+
// src/consent/document.ts
|
|
4
|
+
var OnboardingDocumentFetchError = class extends OnboardingError {
|
|
5
|
+
url;
|
|
6
|
+
constructor(url, detail) {
|
|
7
|
+
super(
|
|
8
|
+
"network_error",
|
|
9
|
+
`Failed to fetch consent document from "${url}": ${detail}`,
|
|
10
|
+
null
|
|
11
|
+
);
|
|
12
|
+
this.name = "OnboardingDocumentFetchError";
|
|
13
|
+
this.url = url;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
function classify(contentType) {
|
|
17
|
+
if (contentType.includes("application/pdf")) return "pdf";
|
|
18
|
+
if (contentType.includes("text/html")) return "html";
|
|
19
|
+
if (contentType.startsWith("text/")) return "text";
|
|
20
|
+
return "binary";
|
|
21
|
+
}
|
|
22
|
+
async function fetchDocumentContent(doc, options = {}) {
|
|
23
|
+
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
24
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
|
|
25
|
+
const url = doc.downloadUrl;
|
|
26
|
+
let response;
|
|
27
|
+
try {
|
|
28
|
+
response = await fetchWithTimeout(url, {
|
|
29
|
+
method: "GET",
|
|
30
|
+
timeoutMs,
|
|
31
|
+
fetchImpl
|
|
32
|
+
});
|
|
33
|
+
} catch (err) {
|
|
34
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
35
|
+
throw new OnboardingDocumentFetchError(url, detail);
|
|
36
|
+
}
|
|
37
|
+
if (response.status < 200 || response.status >= 300) {
|
|
38
|
+
throw new OnboardingDocumentFetchError(
|
|
39
|
+
url,
|
|
40
|
+
`unexpected status ${response.status}`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const rawType = response.headers.get("content-type") ?? "";
|
|
44
|
+
const contentType = rawType.split(";")[0]?.trim().toLowerCase() ?? "";
|
|
45
|
+
const kind = classify(contentType);
|
|
46
|
+
try {
|
|
47
|
+
if (kind === "html" || kind === "text") {
|
|
48
|
+
return { contentType, kind, text: await response.text() };
|
|
49
|
+
}
|
|
50
|
+
return { contentType, kind, blob: await response.blob() };
|
|
51
|
+
} catch (err) {
|
|
52
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
53
|
+
throw new OnboardingDocumentFetchError(url, `body read failed: ${detail}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { OnboardingDocumentFetchError, fetchDocumentContent };
|
|
58
|
+
//# sourceMappingURL=chunk-SEKNVHD3.js.map
|
|
59
|
+
//# sourceMappingURL=chunk-SEKNVHD3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/consent/document.ts"],"names":[],"mappings":";;;AAiDO,IAAM,4BAAA,GAAN,cAA2C,eAAA,CAAgB;AAAA,EAChD,GAAA;AAAA,EAEhB,WAAA,CAAY,KAAa,MAAA,EAAgB;AACvC,IAAA,KAAA;AAAA,MACE,eAAA;AAAA,MACA,CAAA,uCAAA,EAA0C,GAAG,CAAA,GAAA,EAAM,MAAM,CAAA,CAAA;AAAA,MACzD;AAAA,KACF;AACA,IAAA,IAAA,CAAK,IAAA,GAAO,8BAAA;AACZ,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AAAA,EACb;AACF;AAEA,SAAS,SAAS,WAAA,EAA0C;AAC1D,EAAA,IAAI,WAAA,CAAY,QAAA,CAAS,iBAAiB,CAAA,EAAG,OAAO,KAAA;AACpD,EAAA,IAAI,WAAA,CAAY,QAAA,CAAS,WAAW,CAAA,EAAG,OAAO,MAAA;AAC9C,EAAA,IAAI,WAAA,CAAY,UAAA,CAAW,OAAO,CAAA,EAAG,OAAO,MAAA;AAC5C,EAAA,OAAO,QAAA;AACT;AASA,eAAsB,oBAAA,CACpB,GAAA,EACA,OAAA,GAAuC,EAAC,EACP;AACjC,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,KAAA,IAAS,UAAA,CAAW,KAAA;AAC9C,EAAA,MAAM,SAAA,GAAY,QAAQ,SAAA,IAAa,0BAAA;AACvC,EAAA,MAAM,MAAM,GAAA,CAAI,WAAA;AAEhB,EAAA,IAAI,QAAA;AACJ,EAAA,IAAI;AACF,IAAA,QAAA,GAAW,MAAM,iBAAiB,GAAA,EAAK;AAAA,MACrC,MAAA,EAAQ,KAAA;AAAA,MACR,SAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC9D,IAAA,MAAM,IAAI,4BAAA,CAA6B,GAAA,EAAK,MAAM,CAAA;AAAA,EACpD;AAEA,EAAA,IAAI,QAAA,CAAS,MAAA,GAAS,GAAA,IAAO,QAAA,CAAS,UAAU,GAAA,EAAK;AACnD,IAAA,MAAM,IAAI,4BAAA;AAAA,MACR,GAAA;AAAA,MACA,CAAA,kBAAA,EAAqB,SAAS,MAAM,CAAA;AAAA,KACtC;AAAA,EACF;AAEA,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA,IAAK,EAAA;AACxD,EAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,EAAG,IAAA,EAAK,CAAE,WAAA,EAAY,IAAK,EAAA;AACnE,EAAA,MAAM,IAAA,GAAO,SAAS,WAAW,CAAA;AAEjC,EAAA,IAAI;AACF,IAAA,IAAI,IAAA,KAAS,MAAA,IAAU,IAAA,KAAS,MAAA,EAAQ;AACtC,MAAA,OAAO,EAAE,WAAA,EAAa,IAAA,EAAM,MAAM,MAAM,QAAA,CAAS,MAAK,EAAE;AAAA,IAC1D;AACA,IAAA,OAAO,EAAE,WAAA,EAAa,IAAA,EAAM,MAAM,MAAM,QAAA,CAAS,MAAK,EAAE;AAAA,EAC1D,SAAS,GAAA,EAAK;AACZ,IAAA,MAAM,SAAS,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG,CAAA;AAC9D,IAAA,MAAM,IAAI,4BAAA,CAA6B,GAAA,EAAK,CAAA,kBAAA,EAAqB,MAAM,CAAA,CAAE,CAAA;AAAA,EAC3E;AACF","file":"chunk-SEKNVHD3.js","sourcesContent":["/**\n * Headless document-content fetch helper (D543 §5).\n *\n * The consent controller is DOM-free; document RENDERING is the consumer's\n * responsibility (TanStack model — you render the row, we own the state). For\n * `scroll_then_accept` gating to work the doc must be rendered SAME-ORIGIN and\n * inline (a cross-origin iframe cannot report scroll position), so consumers\n * fetch the presigned artifact and render its bytes/text themselves.\n *\n * This helper does the fetch + classification so a consumer doesn't wrestle\n * CORS/content-type detection. It returns the artifact's content-type plus the\n * body as text (for HTML/plain) or a Blob (for PDF/binary). It NEVER renders\n * or sanitizes — the consumer (or the default component) decides how to display\n * it (e.g. sanitize+inject HTML, or PDF.js a blob, or degrade to open-in-tab).\n *\n * A short-TTL presigned GET may fail (expired URL, CORS, offline); the caller\n * gets a typed OnboardingDocumentFetchError so a failed preview degrades\n * gracefully (e.g. fall back to an \"open in a new tab\" affordance) without\n * breaking the consent gate.\n */\n\nimport type { ConsentDocument } from \"./model.js\";\nimport {\n DEFAULT_REQUEST_TIMEOUT_MS,\n fetchWithTimeout,\n} from \"../submit/http.js\";\nimport { OnboardingError } from \"../submit/errors.js\";\n\n/** How the fetched artifact should be treated by a renderer. */\nexport type ConsentDocumentKind = \"html\" | \"text\" | \"pdf\" | \"binary\";\n\nexport interface FetchedConsentDocument {\n /** The raw `Content-Type` header (lower-cased, params stripped). */\n contentType: string;\n /** Classification for the renderer. */\n kind: ConsentDocumentKind;\n /** Present for kind \"html\" | \"text\". */\n text?: string;\n /** Present for kind \"pdf\" | \"binary\". */\n blob?: Blob;\n}\n\nexport interface FetchDocumentContentOptions {\n fetch?: typeof globalThis.fetch;\n /** Per-request timeout (default 15s) — a stalled CDN never hangs the UI. */\n timeoutMs?: number;\n}\n\n/** A failed presigned artifact fetch (expired URL, CORS, offline, non-2xx). */\nexport class OnboardingDocumentFetchError extends OnboardingError {\n public readonly url: string;\n\n constructor(url: string, detail: string) {\n super(\n \"network_error\",\n `Failed to fetch consent document from \"${url}\": ${detail}`,\n null,\n );\n this.name = \"OnboardingDocumentFetchError\";\n this.url = url;\n }\n}\n\nfunction classify(contentType: string): ConsentDocumentKind {\n if (contentType.includes(\"application/pdf\")) return \"pdf\";\n if (contentType.includes(\"text/html\")) return \"html\";\n if (contentType.startsWith(\"text/\")) return \"text\";\n return \"binary\";\n}\n\n/**\n * Fetch a consent document's presigned artifact and return its content-type +\n * body (text for HTML/plain, Blob for PDF/binary).\n *\n * @throws {OnboardingDocumentFetchError} on network failure, timeout, CORS,\n * or a non-2xx response — the caller degrades gracefully (open-in-tab).\n */\nexport async function fetchDocumentContent(\n doc: Pick<ConsentDocument, \"downloadUrl\">,\n options: FetchDocumentContentOptions = {},\n): Promise<FetchedConsentDocument> {\n const fetchImpl = options.fetch ?? globalThis.fetch;\n const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n const url = doc.downloadUrl;\n\n let response: Response;\n try {\n response = await fetchWithTimeout(url, {\n method: \"GET\",\n timeoutMs,\n fetchImpl,\n });\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new OnboardingDocumentFetchError(url, detail);\n }\n\n if (response.status < 200 || response.status >= 300) {\n throw new OnboardingDocumentFetchError(\n url,\n `unexpected status ${response.status}`,\n );\n }\n\n const rawType = response.headers.get(\"content-type\") ?? \"\";\n const contentType = rawType.split(\";\")[0]?.trim().toLowerCase() ?? \"\";\n const kind = classify(contentType);\n\n try {\n if (kind === \"html\" || kind === \"text\") {\n return { contentType, kind, text: await response.text() };\n }\n return { contentType, kind, blob: await response.blob() };\n } catch (err) {\n const detail = err instanceof Error ? err.message : String(err);\n throw new OnboardingDocumentFetchError(url, `body read failed: ${detail}`);\n }\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { z } from 'zod/v3';
|
|
2
|
+
|
|
3
|
+
// src/form/schema.ts
|
|
4
|
+
var contactFormSchema = z.object({
|
|
5
|
+
name: z.string().max(200).optional(),
|
|
6
|
+
companyName: z.string().min(1, "Company name is required").max(200, "Company name must be 200 characters or fewer"),
|
|
7
|
+
contactName: z.string().min(1, "Contact name is required").max(200, "Contact name must be 200 characters or fewer"),
|
|
8
|
+
email: z.string().email("A valid email address is required"),
|
|
9
|
+
phone: z.string().optional(),
|
|
10
|
+
message: z.string().max(4e3, "Message must be 4000 characters or fewer").optional(),
|
|
11
|
+
interestModules: z.array(z.string().min(1)).max(32).default([]),
|
|
12
|
+
sizeBand: z.string().max(80).optional(),
|
|
13
|
+
attribution: z.object({
|
|
14
|
+
campaignTags: z.record(z.string()).optional(),
|
|
15
|
+
referringSite: z.string().max(2048).optional(),
|
|
16
|
+
landingPage: z.string().max(2048).optional(),
|
|
17
|
+
button: z.string().max(120).optional()
|
|
18
|
+
}).strict().optional(),
|
|
19
|
+
privacyNoticeAcknowledged: z.boolean().refine((value) => value, "Privacy notice acknowledgement is required"),
|
|
20
|
+
marketingOptIn: z.boolean(),
|
|
21
|
+
intakeKind: z.enum(["contact", "enquiry"]),
|
|
22
|
+
// Q46 default: a visually-hidden field. Humans leave it empty.
|
|
23
|
+
website: z.string().max(0).optional()
|
|
24
|
+
});
|
|
25
|
+
var leadsWireSchema = contactFormSchema.extend({
|
|
26
|
+
botToken: z.string().min(1, "botToken is required").optional()
|
|
27
|
+
}).strict();
|
|
28
|
+
function validateContactForm(values) {
|
|
29
|
+
return contactFormSchema.safeParse(values);
|
|
30
|
+
}
|
|
31
|
+
function validateLeadsPayload(payload) {
|
|
32
|
+
return leadsWireSchema.safeParse(payload);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { contactFormSchema, leadsWireSchema, validateContactForm, validateLeadsPayload };
|
|
36
|
+
//# sourceMappingURL=chunk-SIMLMQPT.js.map
|
|
37
|
+
//# sourceMappingURL=chunk-SIMLMQPT.js.map
|