@nodii/onboarding 0.1.0 → 0.2.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.
Files changed (56) hide show
  1. package/README.md +46 -0
  2. package/dist/{chunk-KQTS47FC.js → chunk-A3DE2IAH.js} +30 -5
  3. package/dist/chunk-A3DE2IAH.js.map +1 -0
  4. package/dist/{chunk-U6AXKGYQ.js → chunk-DWFZA5T6.js} +10 -8
  5. package/dist/chunk-DWFZA5T6.js.map +1 -0
  6. package/dist/{chunk-F75ZJERM.js → chunk-KFHVZGX6.js} +34 -14
  7. package/dist/chunk-KFHVZGX6.js.map +1 -0
  8. package/dist/{chunk-U56GQITG.js → chunk-NDSBIB3N.js} +25 -5
  9. package/dist/chunk-NDSBIB3N.js.map +1 -0
  10. package/dist/chunk-OLWR5COK.js +10 -0
  11. package/dist/chunk-OLWR5COK.js.map +1 -0
  12. package/dist/{chunk-IPAKPLIF.js → chunk-OVULPWNZ.js} +341 -80
  13. package/dist/chunk-OVULPWNZ.js.map +1 -0
  14. package/dist/{chunk-LVJM4CTG.js → chunk-T7EWURTF.js} +34 -19
  15. package/dist/chunk-T7EWURTF.js.map +1 -0
  16. package/dist/{chunk-BMQINH6O.js → chunk-UHOFGWI7.js} +5 -4
  17. package/dist/chunk-UHOFGWI7.js.map +1 -0
  18. package/dist/{chunk-SIMLMQPT.js → chunk-WKN4U7QF.js} +3 -5
  19. package/dist/chunk-WKN4U7QF.js.map +1 -0
  20. package/dist/{chunk-AZE3NPSY.js → chunk-ZR6X3GSM.js} +3 -3
  21. package/dist/{chunk-AZE3NPSY.js.map → chunk-ZR6X3GSM.js.map} +1 -1
  22. package/dist/{client-CqE2dF9A.d.ts → client-NvqPpfQP.d.ts} +1 -1
  23. package/dist/consent/index.d.ts +3 -3
  24. package/dist/consent/index.js +2 -2
  25. package/dist/{controller-BQb62D0N.d.ts → controller-BLH3wnxl.d.ts} +1 -1
  26. package/dist/dynamic/index.d.ts +13 -5
  27. package/dist/dynamic/index.js +4 -3
  28. package/dist/form/index.d.ts +12 -4
  29. package/dist/form/index.js +2 -2
  30. package/dist/{index-Dqfa890U.d.ts → index-BMSbQGWP.d.ts} +23 -3
  31. package/dist/index.d.ts +8 -8
  32. package/dist/index.js +9 -8
  33. package/dist/{model-mnjAEtKe.d.ts → model-BI_I-D_V.d.ts} +16 -2
  34. package/dist/{model-ESLSEbi0.d.ts → model-CEwvHlWA.d.ts} +14 -1
  35. package/dist/render-EWQXF73I.js +5 -0
  36. package/dist/{render-DC7P2BGQ.js.map → render-EWQXF73I.js.map} +1 -1
  37. package/dist/{schema-BrXb9gnh.d.ts → schema-BrtjpXfL.d.ts} +0 -10
  38. package/dist/{signup-client-BL5DfarJ.d.ts → signup-client-CS95nkVO.d.ts} +4 -4
  39. package/dist/spec/index.d.ts +3 -3
  40. package/dist/spec/index.js +2 -2
  41. package/dist/submit/index.d.ts +5 -5
  42. package/dist/submit/index.js +3 -2
  43. package/dist/viewer/index.d.ts +3 -3
  44. package/dist/viewer/index.js +1 -1
  45. package/dist/widget/index.d.ts +61 -22
  46. package/dist/widget/index.js +9 -8
  47. package/package.json +1 -1
  48. package/dist/chunk-BMQINH6O.js.map +0 -1
  49. package/dist/chunk-F75ZJERM.js.map +0 -1
  50. package/dist/chunk-IPAKPLIF.js.map +0 -1
  51. package/dist/chunk-KQTS47FC.js.map +0 -1
  52. package/dist/chunk-LVJM4CTG.js.map +0 -1
  53. package/dist/chunk-SIMLMQPT.js.map +0 -1
  54. package/dist/chunk-U56GQITG.js.map +0 -1
  55. package/dist/chunk-U6AXKGYQ.js.map +0 -1
  56. package/dist/render-DC7P2BGQ.js +0 -5
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/spec/model.ts","../src/spec/client.ts","../src/spec/pin-state.ts"],"names":[],"mappings":"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","file":"chunk-F75ZJERM.js","sourcesContent":["/**\n * D540 §1 onboarding-spec model — mirrors the LOCKED hub REST contract:\n * GET /api/v1/public/onboarding/spec (PublicOnboardingSpecResponse)\n *\n * Response shape (hub JSON Schema, both tiers identical):\n * {\n * specVersion: string (monotonic; echo on submit; stale ⇒ 409),\n * onboarderTier: \"platform\" | \"tenant\",\n * botChallenge: { provider: \"recaptcha\", siteKey: string },\n * forms: {\n * contact: { fields: SpecField[] },\n * signup: { steps: [{ stage: \"lead\"|\"prospect\"|\"activation\",\n * fields: SpecField[] }] }\n * }\n * }\n *\n * SpecField (required: key, type, label, required):\n * { key, type, label, required, validation?, options?, serviceSelection?,\n * piiClass?: \"none\"|\"context\"|\"always\"|\"reference\" }\n *\n * The Zod schema below validates a fetched spec BEFORE the SDK renders\n * anything from it — a malformed spec throws OnboardingSpecInvalidError\n * (a half-parsed spec could silently drop required fields).\n */\n\nimport { z } from \"zod/v3\";\nimport { consentPackSchema } from \"../consent/model.js\";\n\nexport type OnboarderTier = \"platform\" | \"tenant\";\nexport type PiiClass = \"none\" | \"context\" | \"always\" | \"reference\";\nexport type SpecStage = \"lead\" | \"prospect\" | \"activation\";\nexport type TerminalStage = \"prospect\" | \"inactive\" | \"active\";\n\n/**\n * Field keys are interpolated into DOM element ids and (historically) CSS\n * selectors by the widget layer. Constrain them to a strict identifier\n * alphabet so a MALICIOUS or compromised onboarder spec cannot smuggle CSS\n * metacharacters or selector-breakout payloads (e.g. `evil], [onclick=…`)\n * through the fetched spec. A spec with an out-of-alphabet key is REJECTED\n * at parse time → OnboardingSpecInvalidError (fail-closed; never rendered).\n * This is layer 1; the widget also CSS.escapes ids as defense-in-depth.\n */\nexport const FIELD_KEY_PATTERN = /^[A-Za-z0-9_-]+$/;\n\nexport const specFieldSchema = z.object({\n key: z\n .string()\n .min(1)\n .regex(\n FIELD_KEY_PATTERN,\n \"field key must contain only letters, digits, underscore, or hyphen\",\n ),\n type: z.string().min(1),\n label: z.string(),\n required: z.boolean(),\n validation: z.record(z.unknown()).optional(),\n options: z.array(z.unknown()).optional(),\n serviceSelection: z.boolean().optional(),\n piiClass: z.enum([\"none\", \"context\", \"always\", \"reference\"]).optional(),\n});\n\nexport type SpecField = z.infer<typeof specFieldSchema>;\n\nexport const specStepSchema = z.object({\n stage: z.enum([\"lead\", \"prospect\", \"activation\"]),\n fields: z.array(specFieldSchema),\n});\n\nexport type SpecStep = z.infer<typeof specStepSchema>;\n\nexport const onboardingSpecSchema = z.object({\n specVersion: z.string().min(1),\n onboarderTier: z.enum([\"platform\", \"tenant\"]),\n // D1444: omitted when the onboarder has explicitly disabled bot checking.\n botChallenge: z\n .object({\n provider: z.literal(\"recaptcha\"),\n siteKey: z.string(),\n })\n .optional(),\n forms: z.object({\n // ADVISORY-ONLY (by design, plan §12.2 / D540): the Contact-Us form is\n // INTENTIONALLY a fixed barebones shape (name/email/phone/message) and is\n // NOT onboarder-configurable. `mountContactForm` renders that fixed set\n // directly and does NOT read forms.contact.fields — the field is modeled\n // (and validated) so the SDK can round-trip the full spec, but it drives\n // no rendering. Only forms.signup is spec-driven (the dynamic stepper).\n contact: z.object({ fields: z.array(specFieldSchema) }),\n signup: z.object({ steps: z.array(specStepSchema) }),\n }),\n // D543 §4 ConsentPack extension. OPTIONAL for backward-compat (D543\n // \"pre-ConsentPack submits still parse\"): an onboarder with no required\n // legal docs serves no block, and the consent stage is omitted from the\n // flow. When PRESENT it is validated fully (fail-closed) — a malformed\n // consentPack throws OnboardingSpecInvalidError, never rendered half-parsed.\n consentPack: consentPackSchema.optional(),\n});\n\nexport type OnboardingSpec = z.infer<typeof onboardingSpecSchema>;\n\n/**\n * Parse an unknown value as an OnboardingSpec.\n * Returns a SafeParseReturnType (inferred).\n */\nexport function validateOnboardingSpec(value: unknown) {\n return onboardingSpecSchema.safeParse(value);\n}\n","/**\n * Config-fetch client for GET /api/v1/public/onboarding/spec (D540 §1/§3).\n *\n * - The onboarder is derived SERVER-side from the request Host (D536) —\n * it is NOT sent by the client. The `onboarder` value here is purely the\n * CLIENT-side cache key (D540 §3: \"cache key (onboarder, specVersion)\").\n * - The spec response is validated against the LOCKED D540 shape before\n * it is returned; a malformed spec throws OnboardingSpecInvalidError.\n * - Cache semantics: every successful fetch is stored under\n * (onboarder, specVersion) and as the onboarder's \"latest\". The versioned\n * entries let the 409 spec_stale flow diff the previously-served version\n * against the refetched one (see `diffSpecFields` + the signup widget's\n * handleSpecStale, which reads the cached prior version before refetching).\n */\n\nimport {\n OnboardingNetworkError,\n OnboardingRateLimitError,\n OnboardingServerError,\n OnboardingSpecInvalidError,\n} from \"../submit/errors.js\";\nimport {\n DEFAULT_REQUEST_TIMEOUT_MS,\n fetchWithTimeout,\n} from \"../submit/http.js\";\nimport {\n validateOnboardingSpec,\n type OnboardingSpec,\n type SpecField,\n} from \"./model.js\";\n\nconst SPEC_PATH = \"/api/v1/public/onboarding/spec\";\n\n/**\n * In-memory spec cache keyed by (onboarder, specVersion), with a \"latest\"\n * pointer per onboarder. Purely client-side; no TTL — the reject-stale\n * policy (409 spec_stale on submit) is the authoritative staleness signal,\n * and a refetch overwrites \"latest\".\n */\nexport class OnboardingSpecCache {\n private readonly byVersion = new Map<string, OnboardingSpec>();\n private readonly latest = new Map<string, OnboardingSpec>();\n\n /**\n * Collision-proof composite key. Uses JSON.stringify of the tuple so an\n * onboarder or version containing the delimiter can never alias another\n * entry — and, critically, contains NO control characters (an earlier\n * NUL-separator made git treat this whole file as binary/undiffable).\n */\n private static versionKey(onboarder: string, specVersion: string): string {\n return JSON.stringify([onboarder, specVersion]);\n }\n\n get(onboarder: string, specVersion: string): OnboardingSpec | undefined {\n return this.byVersion.get(\n OnboardingSpecCache.versionKey(onboarder, specVersion),\n );\n }\n\n getLatest(onboarder: string): OnboardingSpec | undefined {\n return this.latest.get(onboarder);\n }\n\n set(onboarder: string, spec: OnboardingSpec): void {\n this.byVersion.set(\n OnboardingSpecCache.versionKey(onboarder, spec.specVersion),\n spec,\n );\n this.latest.set(onboarder, spec);\n }\n\n clear(): void {\n this.byVersion.clear();\n this.latest.clear();\n }\n}\n\n/** Module-level default cache (one per page). Injectable for tests/apps. */\nexport const defaultSpecCache = new OnboardingSpecCache();\n\n/**\n * Diff two spec versions' signup field sets — used by the 409 spec_stale\n * flow to tell the user WHAT changed. Compares by field key across all\n * signup steps.\n */\nexport interface SpecFieldDiff {\n added: string[];\n removed: string[];\n changed: string[];\n}\n\nfunction signupFieldMap(spec: OnboardingSpec): Map<string, SpecField> {\n const map = new Map<string, SpecField>();\n for (const step of spec.forms.signup.steps) {\n for (const field of step.fields) map.set(field.key, field);\n }\n return map;\n}\n\nexport function diffSpecFields(\n prev: OnboardingSpec,\n next: OnboardingSpec,\n): SpecFieldDiff {\n const prevMap = signupFieldMap(prev);\n const nextMap = signupFieldMap(next);\n const added: string[] = [];\n const removed: string[] = [];\n const changed: string[] = [];\n for (const key of nextMap.keys()) {\n if (!prevMap.has(key)) added.push(key);\n }\n for (const [key, prevField] of prevMap) {\n const nextField = nextMap.get(key);\n if (!nextField) {\n removed.push(key);\n continue;\n }\n if (JSON.stringify(prevField) !== JSON.stringify(nextField)) {\n changed.push(key);\n }\n }\n return {\n added: added.sort(),\n removed: removed.sort(),\n changed: changed.sort(),\n };\n}\n\nexport interface SpecFetchOptions {\n baseUrl: string;\n /**\n * Client-side cache key ONLY (never transmitted; trust is host-derived\n * per D536). Use the onboarder slug/id your embed is configured with.\n */\n onboarder: string;\n /** Custom fetch implementation (defaults to globalThis.fetch). */\n fetch?: typeof globalThis.fetch;\n /** Cache to read/write (defaults to the module-level cache). */\n cache?: OnboardingSpecCache;\n /**\n * Request timeout in ms (default 15s). A stalled intake aborts with\n * OnboardingNetworkError so the boot doesn't hang on \"Loading signup form…\".\n */\n timeoutMs?: number;\n /**\n * When true, return the cached \"latest\" for this onboarder if present\n * WITHOUT a network round-trip. Default false (spec fetches are cheap\n * and the server bumps specVersion on any change). The signup widget's\n * boot passes preferCached:true so a remount reuses the loaded spec.\n */\n preferCached?: boolean;\n}\n\nfunction buildUrl(baseUrl: string, path: string): string {\n const base = baseUrl.endsWith(\"/\") ? baseUrl.slice(0, -1) : baseUrl;\n return `${base}${path}`;\n}\n\n/**\n * Fetch (and validate, and cache) the onboarding spec.\n *\n * @throws {OnboardingSpecInvalidError} response does not match D540 §1\n * @throws {OnboardingRateLimitError} on 429\n * @throws {OnboardingServerError} on any other non-2xx status\n * @throws {OnboardingNetworkError} on network failure OR timeout\n */\nexport async function fetchOnboardingSpec(\n options: SpecFetchOptions,\n): Promise<OnboardingSpec> {\n const cache = options.cache ?? defaultSpecCache;\n\n if (options.preferCached) {\n const cached = cache.getLatest(options.onboarder);\n if (cached) return cached;\n }\n\n const fetchImpl = options.fetch ?? globalThis.fetch;\n const timeoutMs = options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n const url = buildUrl(options.baseUrl, SPEC_PATH);\n\n let response: Response;\n try {\n response = await fetchWithTimeout(url, {\n method: \"GET\",\n timeoutMs,\n fetchImpl,\n });\n } catch (err) {\n throw new OnboardingNetworkError(err);\n }\n\n if (response.status === 429) {\n const retryAfterHeader = response.headers.get(\"retry-after\");\n const retryAfter = retryAfterHeader\n ? Number.parseInt(retryAfterHeader, 10)\n : Number.NaN;\n throw new OnboardingRateLimitError(\n Number.isNaN(retryAfter) ? null : retryAfter,\n );\n }\n if (response.status < 200 || response.status >= 300) {\n throw new OnboardingServerError(\n response.status,\n `Spec fetch failed with status ${response.status}`,\n );\n }\n\n let body: unknown;\n try {\n body = await response.json();\n } catch {\n throw new OnboardingSpecInvalidError(\"response body is not JSON\");\n }\n\n const parsed = validateOnboardingSpec(body);\n if (!parsed.success) {\n const detail = parsed.error.issues\n .slice(0, 5)\n .map((i) => `${i.path.join(\".\") || \"(root)\"}: ${i.message}`)\n .join(\"; \");\n throw new OnboardingSpecInvalidError(detail);\n }\n\n cache.set(options.onboarder, parsed.data);\n return parsed.data;\n}\n","import {\n OnboardingServerError,\n OnboardingValidationError,\n} from \"../submit/errors.js\";\nimport {\n DEFAULT_REQUEST_TIMEOUT_MS,\n fetchWithTimeout,\n} from \"../submit/http.js\";\n\nexport interface PinStateResult {\n pin: string;\n stateIso: string | null;\n}\n\nexport async function fetchPinState(options: {\n baseUrl: string;\n pin: string;\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n}): Promise<PinStateResult> {\n const pin = options.pin.trim();\n if (!/^[1-9][0-9]{5}$/.test(pin)) {\n throw new OnboardingValidationError(\n \"PIN must be a 6-digit Indian PIN code\",\n );\n }\n const response = await fetchWithTimeout(\n `${options.baseUrl.replace(/\\/$/, \"\")}/api/v1/public/onboarding/pin-state?pin=${encodeURIComponent(pin)}`,\n {\n method: \"GET\",\n fetchImpl: options.fetch ?? globalThis.fetch,\n timeoutMs: options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS,\n },\n );\n if (!response.ok) throw new OnboardingServerError(response.status);\n const value = (await response.json()) as {\n pin?: unknown;\n state_iso?: unknown;\n };\n if (\n value.pin !== pin ||\n (value.state_iso !== null && typeof value.state_iso !== \"string\")\n ) {\n throw new OnboardingServerError(\n response.status,\n \"Invalid PIN-state response\",\n );\n }\n return { pin, stateIso: value.state_iso };\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/widget/dom-utils.ts","../src/widget/styles.ts","../src/widget/contact-form.ts","../src/widget/consent-step.ts","../src/widget/signup-form.ts","../src/widget/index.ts"],"names":["el"],"mappings":"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","file":"chunk-IPAKPLIF.js","sourcesContent":["/**\n * Shared DOM helpers for the widget layer.\n *\n * `idSelector` builds a `#id` CSS selector with the id CSS-escaped, so a field\n * key (which originates in the fetched onboarder spec) can never break out of\n * the selector or match unintended nodes. This is defense-in-depth: the spec\n * model already constrains field keys to `[A-Za-z0-9_-]+` (FIELD_KEY_PATTERN),\n * but the escaping guarantees selector safety even for the widget's own\n * internally-composed ids and for any future relaxation of that alphabet.\n */\n\n/**\n * CSS-escape a string for safe use as an identifier in a selector.\n * Uses the standard `CSS.escape` when available (all modern browsers), with a\n * spec-compliant-enough fallback for non-DOM/test runtimes: escape everything\n * that is not an ASCII identifier char.\n */\nexport function cssEscape(value: string): string {\n const g = globalThis as { CSS?: { escape?: (v: string) => string } };\n if (g.CSS && typeof g.CSS.escape === \"function\") {\n return g.CSS.escape(value);\n }\n // Fallback: backslash-escape any char outside [A-Za-z0-9_-]. Sufficient to\n // neutralize CSS metacharacters ([]().,#*:>+~ whitespace, quotes, etc.).\n return value.replace(/[^A-Za-z0-9_-]/g, (ch) => `\\\\${ch}`);\n}\n\n/** Build a safe `#id` selector with the id CSS-escaped. */\nexport function idSelector(id: string): string {\n return `#${cssEscape(id)}`;\n}\n","/// <reference lib=\"dom\" />\n/// <reference lib=\"dom.iterable\" />\n/**\n * Default CSS for the onboarding contact form widget.\n *\n * Uses CSS custom properties (variables) for theming. Consumers override\n * these on the host element or globally:\n *\n * --nodii-onboarding-font-family\n * --nodii-onboarding-primary-color\n * --nodii-onboarding-primary-hover\n * --nodii-onboarding-error-color\n * --nodii-onboarding-border-color\n * --nodii-onboarding-input-bg\n * --nodii-onboarding-label-color\n * --nodii-onboarding-radius\n * --nodii-onboarding-spacing\n *\n * The widget scopes all styles under `.nodii-onboarding-widget` to avoid\n * leaking into the host page.\n */\n\nexport const DEFAULT_WIDGET_CSS = `\n.nodii-onboarding-widget {\n --_font: var(--nodii-onboarding-font-family, system-ui, -apple-system, sans-serif);\n --_primary: var(--nodii-onboarding-primary-color, #2563eb);\n --_primary-hover: var(--nodii-onboarding-primary-hover, #1d4ed8);\n --_error: var(--nodii-onboarding-error-color, #dc2626);\n --_border: var(--nodii-onboarding-border-color, #d1d5db);\n --_input-bg: var(--nodii-onboarding-input-bg, #fff);\n --_label: var(--nodii-onboarding-label-color, #374151);\n --_radius: var(--nodii-onboarding-radius, 6px);\n --_spacing: var(--nodii-onboarding-spacing, 16px);\n\n font-family: var(--_font);\n box-sizing: border-box;\n}\n\n.nodii-onboarding-widget *,\n.nodii-onboarding-widget *::before,\n.nodii-onboarding-widget *::after {\n box-sizing: inherit;\n}\n\n.nodii-onboarding-field {\n display: flex;\n flex-direction: column;\n gap: calc(var(--_spacing) * 0.25);\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-label {\n font-size: 0.875rem;\n font-weight: 500;\n color: var(--_label);\n}\n\n.nodii-onboarding-label.required::after {\n content: \" *\";\n color: var(--_error);\n}\n\n.nodii-onboarding-input,\n.nodii-onboarding-textarea {\n width: 100%;\n padding: calc(var(--_spacing) * 0.5) calc(var(--_spacing) * 0.75);\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n background: var(--_input-bg);\n font-family: var(--_font);\n font-size: 1rem;\n line-height: 1.5;\n outline: none;\n transition: border-color 0.15s ease;\n}\n\n.nodii-onboarding-input:focus,\n.nodii-onboarding-textarea:focus {\n border-color: var(--_primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_primary) 20%, transparent);\n}\n\n.nodii-onboarding-input.has-error,\n.nodii-onboarding-textarea.has-error {\n border-color: var(--_error);\n}\n\n.nodii-onboarding-textarea {\n min-height: 100px;\n resize: vertical;\n}\n\n.nodii-onboarding-field-error {\n font-size: 0.75rem;\n color: var(--_error);\n margin-top: 2px;\n}\n\n.nodii-onboarding-server-error {\n padding: calc(var(--_spacing) * 0.75);\n border-radius: var(--_radius);\n background: color-mix(in srgb, var(--_error) 8%, transparent);\n border: 1px solid color-mix(in srgb, var(--_error) 30%, transparent);\n color: var(--_error);\n font-size: 0.875rem;\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-success {\n padding: var(--_spacing);\n border-radius: var(--_radius);\n background: #f0fdf4;\n border: 1px solid #bbf7d0;\n color: #15803d;\n font-size: 0.9375rem;\n text-align: center;\n}\n\n.nodii-onboarding-submit-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n padding: calc(var(--_spacing) * 0.625) var(--_spacing);\n background: var(--_primary);\n color: #fff;\n border: none;\n border-radius: var(--_radius);\n font-family: var(--_font);\n font-size: 1rem;\n font-weight: 500;\n cursor: pointer;\n transition: background 0.15s ease;\n}\n\n.nodii-onboarding-submit-btn:hover:not(:disabled) {\n background: var(--_primary-hover);\n}\n\n.nodii-onboarding-submit-btn:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.nodii-onboarding-spinner {\n display: inline-block;\n width: 1em;\n height: 1em;\n border: 2px solid rgba(255,255,255,0.4);\n border-top-color: #fff;\n border-radius: 50%;\n animation: nodii-spin 0.6s linear infinite;\n margin-right: 0.5em;\n}\n\n@keyframes nodii-spin {\n to { transform: rotate(360deg); }\n}\n\n.nodii-onboarding-recaptcha-notice {\n font-size: 0.7rem;\n color: #6b7280;\n margin-top: calc(var(--_spacing) * 0.5);\n text-align: center;\n}\n\n.nodii-onboarding-recaptcha-notice a {\n color: inherit;\n}\n\n/* ── dynamic stepper (signup form) ── */\n\n.nodii-onboarding-steps {\n display: flex;\n gap: calc(var(--_spacing) * 0.5);\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-step-dot {\n flex: 1;\n height: 4px;\n border-radius: 2px;\n background: var(--_border);\n}\n\n.nodii-onboarding-step-dot.active {\n background: var(--_primary);\n}\n\n.nodii-onboarding-stage-title {\n font-size: 1.0625rem;\n font-weight: 600;\n color: var(--_label);\n margin: 0 0 var(--_spacing) 0;\n}\n\n.nodii-onboarding-nav {\n display: flex;\n gap: calc(var(--_spacing) * 0.5);\n margin-top: var(--_spacing);\n}\n\n.nodii-onboarding-back-btn {\n padding: calc(var(--_spacing) * 0.625) var(--_spacing);\n background: transparent;\n color: var(--_label);\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n font-family: var(--_font);\n font-size: 1rem;\n cursor: pointer;\n}\n\n.nodii-onboarding-stale-banner {\n padding: calc(var(--_spacing) * 0.75);\n border-radius: var(--_radius);\n background: #fffbeb;\n border: 1px solid #fcd34d;\n color: #92400e;\n font-size: 0.875rem;\n margin-bottom: var(--_spacing);\n}\n\n.nodii-onboarding-consent-row {\n display: flex;\n align-items: flex-start;\n gap: calc(var(--_spacing) * 0.5);\n margin-bottom: calc(var(--_spacing) * 0.5);\n font-size: 0.875rem;\n color: var(--_label);\n}\n\n.nodii-onboarding-consent-row input[type=\"checkbox\"] {\n margin-top: 3px;\n}\n\n.nodii-onboarding-account-section {\n border-top: 1px solid var(--_border);\n margin-top: var(--_spacing);\n padding-top: var(--_spacing);\n}\n\n.nodii-onboarding-loading {\n padding: var(--_spacing);\n text-align: center;\n color: var(--_label);\n}\n\n/* ── D543 ConsentPack step (full-width, generous spacing) ── */\n\n.nodii-onboarding-consent-stage {\n /* Full-bleed within the widget host — consent cards may span the page. */\n width: 100%;\n display: flex;\n flex-direction: column;\n gap: calc(var(--_spacing) * 2);\n margin: calc(var(--_spacing) * 1.5) 0;\n}\n\n.nodii-onboarding-consent-intro {\n font-size: 0.9375rem;\n color: var(--_label);\n margin: 0 0 calc(var(--_spacing) * 0.5) 0;\n line-height: 1.6;\n}\n\n.nodii-onboarding-consent-card {\n width: 100%;\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n background: var(--_input-bg);\n padding: calc(var(--_spacing) * 1.5);\n display: flex;\n flex-direction: column;\n gap: var(--_spacing);\n}\n\n.nodii-onboarding-consent-card.is-stale {\n border-color: #fcd34d;\n background: #fffbeb;\n}\n\n.nodii-onboarding-consent-card.has-error {\n border-color: var(--_error);\n}\n\n.nodii-onboarding-consent-title {\n font-size: 1.125rem;\n font-weight: 600;\n color: var(--_label);\n margin: 0;\n}\n\n.nodii-onboarding-consent-stale-tag {\n font-size: 0.8125rem;\n font-weight: 500;\n color: #92400e;\n}\n\n.nodii-onboarding-consent-gate {\n width: 100%;\n}\n\n.nodii-onboarding-consent-scrollbox {\n width: 100%;\n height: 360px;\n overflow-y: auto;\n border: 1px solid var(--_border);\n border-radius: var(--_radius);\n background: #fff;\n position: relative;\n}\n\n.nodii-onboarding-consent-scrollbox:focus {\n outline: none;\n border-color: var(--_primary);\n box-shadow: 0 0 0 3px color-mix(in srgb, var(--_primary) 20%, transparent);\n}\n\n/* Inline, same-origin document content (no iframe). Rendered by the default\n viewer: sanitized HTML/markdown, escaped plain text, or PDF.js canvases. */\n.nodii-onboarding-consent-doc-body {\n padding: var(--_spacing);\n font-size: 0.9375rem;\n line-height: 1.7;\n color: var(--_label);\n word-break: break-word;\n}\n\n.nodii-onboarding-consent-doc-body:not(.nodii-consent-pdf) {\n white-space: pre-wrap;\n}\n\n.nodii-onboarding-consent-doc-loading {\n padding: var(--_spacing);\n color: #6b7280;\n font-size: 0.875rem;\n}\n\n.nodii-consent-pdf {\n display: flex;\n flex-direction: column;\n gap: var(--_spacing);\n white-space: normal;\n}\n\n.nodii-consent-pdf-page {\n max-width: 100%;\n height: auto;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);\n}\n\n.nodii-onboarding-consent-note {\n font-size: 0.8125rem;\n color: #6b7280;\n margin: calc(var(--_spacing) * 0.5) 0 0 0;\n}\n\n/* A gated doc that could not be rendered inline: the gate stays unsatisfiable\n (accept disabled); we surface a clear error + Retry. NO click-to-satisfy. */\n.nodii-onboarding-consent-unrenderable {\n display: flex;\n flex-direction: column;\n gap: calc(var(--_spacing) * 0.5);\n padding: var(--_spacing);\n border: 1px solid color-mix(in srgb, var(--_error) 30%, transparent);\n border-radius: var(--_radius);\n background: color-mix(in srgb, var(--_error) 6%, transparent);\n}\n\n.nodii-onboarding-consent-retry {\n align-self: flex-start;\n padding: calc(var(--_spacing) * 0.5) var(--_spacing);\n background: transparent;\n color: var(--_primary);\n border: 1px solid var(--_primary);\n border-radius: var(--_radius);\n font-family: var(--_font);\n font-size: 0.875rem;\n cursor: pointer;\n}\n\n.nodii-onboarding-consent-open-row,\n.nodii-onboarding-consent-preview-row {\n display: flex;\n}\n\n.nodii-onboarding-consent-open {\n display: inline-flex;\n align-items: center;\n padding: calc(var(--_spacing) * 0.625) var(--_spacing);\n border: 1px solid var(--_primary);\n border-radius: var(--_radius);\n color: var(--_primary);\n text-decoration: none;\n font-size: 0.9375rem;\n font-weight: 500;\n}\n\n.nodii-onboarding-consent-open:hover {\n background: color-mix(in srgb, var(--_primary) 8%, transparent);\n}\n\n.nodii-onboarding-consent-preview {\n font-size: 0.875rem;\n color: var(--_primary);\n}\n\n.nodii-onboarding-consent-accept-row {\n display: flex;\n align-items: flex-start;\n gap: calc(var(--_spacing) * 0.5);\n}\n\n.nodii-onboarding-consent-accept {\n margin-top: 3px;\n width: 1.125rem;\n height: 1.125rem;\n}\n\n.nodii-onboarding-consent-accept:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.nodii-onboarding-consent-accept-label {\n font-size: 0.9375rem;\n color: var(--_label);\n line-height: 1.5;\n}\n\n.nodii-onboarding-consent-required {\n color: var(--_error);\n}\n`;\n\n/**\n * Inject the default widget CSS once into the document head.\n * Idempotent — will not add a duplicate style tag.\n */\nexport function injectWidgetStyles(): void {\n if (typeof document === \"undefined\") return;\n const styleId = \"__nodii_onboarding_styles__\";\n if (document.getElementById(styleId)) return;\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = DEFAULT_WIDGET_CSS;\n document.head.appendChild(style);\n}\n","/// <reference lib=\"dom\" />\n/// <reference lib=\"dom.iterable\" />\n/**\n * Default vanilla-TS contact form widget.\n *\n * Renders a form into a host element and handles the full lifecycle:\n * 1. Render fields (name, email, phone, message)\n * 2. Client-side validation on submit\n * 3. reCAPTCHA token acquisition (D537)\n * 4. POST to /api/v1/public/onboarding/leads via submit client\n * 5. Retry on 5xx with SAME idempotency key\n * 6. Show success or error state\n *\n * No React or framework required. CSS via injectWidgetStyles().\n */\n\nimport {\n createContactFormState,\n type ContactFormControl,\n type FieldError,\n} from \"../form/state.js\";\nimport type { ContactFormValues } from \"../form/schema.js\";\nimport {\n submitLead,\n generateIdempotencyKey,\n computePayloadFingerprint,\n} from \"../submit/client.js\";\nimport {\n OnboardingBotChallengeError,\n OnboardingRateLimitError,\n} from \"../submit/errors.js\";\nimport { executeRecaptcha, loadRecaptcha } from \"../recaptcha/loader.js\";\nimport { idSelector } from \"./dom-utils.js\";\nimport { injectWidgetStyles } from \"./styles.js\";\n\nexport interface ContactFormMountOptions {\n /**\n * The onboarder identifier (slug or UUID).\n *\n * NOT transmitted on the wire — by design. Per LOCKED D536, onboarder\n * trust/scoping is derived server-side from the request Host at the edge\n * (\"onboarder derived from the bundle, never client-supplied\", D540 §1);\n * a client-supplied identifier is never trusted and therefore never sent.\n *\n * This option is reserved for Phase 2, where it becomes the client-side\n * cache key for the spec-fetch (`(onboarder, specVersion)` per D540 §3).\n * In Phase 1 it has no runtime effect.\n */\n onboarder: string;\n /**\n * Base URL for the intake service.\n * e.g. \"https://api.acme.nucleus-cloud.in\"\n */\n baseUrl: string;\n /**\n * reCAPTCHA v3 site key. Obtained from the spec endpoint (D540 §1)\n * or passed directly in Phase 1 before spec-fetch is wired.\n */\n siteKey?: string;\n /**\n * Which form to render. Phase 1 supports \"contact\" only.\n * Phase 2 will add \"signup\" (dynamic stepper from spec).\n */\n form: \"contact\";\n /** Called after a successful lead submission. */\n onSuccess?: () => void;\n /** Called on non-retryable errors (bot challenge, rate limit). */\n onError?: (error: unknown) => void;\n /** Custom fetch implementation (defaults to globalThis.fetch). */\n fetch?: typeof globalThis.fetch;\n /**\n * Per-request timeout in ms (default 15s), applied to BOTH the reCAPTCHA\n * execute() and the submit POST so a hung dependency re-enables the form.\n */\n timeoutMs?: number;\n /** Success message override. */\n successMessage?: string;\n /** Submit button label override. */\n submitLabel?: string;\n}\n\nexport interface MountedWidget {\n /** Unmount and clean up the widget from the host element. */\n unmount(): void;\n /** Reset the form to its initial state. */\n reset(): void;\n}\n\nfunction el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs: Record<string, string> = {},\n children: Array<HTMLElement | Text | string> = [],\n): HTMLElementTagNameMap[K] {\n const element = document.createElement(tag);\n for (const [key, value] of Object.entries(attrs)) {\n element.setAttribute(key, value);\n }\n for (const child of children) {\n if (typeof child === \"string\") {\n element.appendChild(document.createTextNode(child));\n } else {\n element.appendChild(child);\n }\n }\n return element;\n}\n\nfunction createFieldEl(\n id: string,\n label: string,\n input: HTMLInputElement | HTMLTextAreaElement,\n required: boolean,\n): HTMLElement {\n const labelEl = el(\n \"label\",\n { for: id, class: `nodii-onboarding-label${required ? \" required\" : \"\"}` },\n [label],\n );\n const errorEl = el(\"div\", {\n class: \"nodii-onboarding-field-error\",\n id: `${id}-error`,\n role: \"alert\",\n \"aria-live\": \"polite\",\n });\n const field = el(\"div\", { class: \"nodii-onboarding-field\" }, [\n labelEl,\n input,\n errorEl,\n ]);\n return field;\n}\n\nfunction setFieldError(\n container: HTMLElement,\n fieldId: string,\n message: string,\n): void {\n // CSS-escape the id: fieldId derives from spec field keys — never build a\n // selector from unescaped, spec-controlled input.\n const errorEl = container.querySelector(idSelector(`${fieldId}-error`));\n if (errorEl) errorEl.textContent = message;\n const inputEl = container.querySelector(idSelector(fieldId));\n if (inputEl) inputEl.classList.add(\"has-error\");\n}\n\nfunction clearFieldErrors(container: HTMLElement): void {\n for (const el of container.querySelectorAll(\n \".nodii-onboarding-field-error\",\n )) {\n el.textContent = \"\";\n }\n for (const el of container.querySelectorAll(\".has-error\")) {\n el.classList.remove(\"has-error\");\n }\n}\n\nfunction applyErrors(container: HTMLElement, errors: FieldError[]): void {\n clearFieldErrors(container);\n for (const err of errors) {\n // Zod paths are bare field names (\"name\", \"email\"); the DOM ids carry\n // the \"nodii-\" prefix (\"nodii-name\"). Map explicitly — a bare path\n // would querySelector nothing and silently drop the error display.\n setFieldError(container, `nodii-${err.path}`, err.message);\n }\n}\n\n/**\n * Mount the contact form widget into a host element.\n *\n * @example\n * ```ts\n * import { OnboardingWidget } from \"@nodii/onboarding/widget\";\n * const widget = OnboardingWidget.mount(document.getElementById(\"signup\"), {\n * onboarder: \"acme-corp\",\n * form: \"contact\",\n * baseUrl: \"https://api.acme.nucleus-cloud.in\",\n * siteKey: \"6Lc...\",\n * });\n * ```\n */\nexport function mountContactForm(\n host: HTMLElement,\n options: ContactFormMountOptions,\n): MountedWidget {\n injectWidgetStyles();\n\n const formControl: ContactFormControl = createContactFormState();\n\n // Pre-load reCAPTCHA script to minimize latency at submit time.\n // Non-fatal: the loader evicts its cache on failure, so a failed\n // pre-load genuinely retries from scratch at submit time.\n if (options.siteKey) {\n loadRecaptcha(options.siteKey).catch(() => {\n // Swallowed by design — executeRecaptcha at submit re-attempts.\n });\n }\n\n // --- Build DOM ---\n const wrapper = el(\"div\", { class: \"nodii-onboarding-widget\" });\n\n const nameInput = el(\"input\", {\n type: \"text\",\n id: \"nodii-name\",\n name: \"name\",\n class: \"nodii-onboarding-input\",\n placeholder: \"Your name\",\n autocomplete: \"name\",\n maxlength: \"200\",\n required: \"required\",\n }) as HTMLInputElement;\n\n const emailInput = el(\"input\", {\n type: \"email\",\n id: \"nodii-email\",\n name: \"email\",\n class: \"nodii-onboarding-input\",\n placeholder: \"you@company.com\",\n autocomplete: \"email\",\n required: \"required\",\n }) as HTMLInputElement;\n\n const phoneInput = el(\"input\", {\n type: \"tel\",\n id: \"nodii-phone\",\n name: \"phone\",\n class: \"nodii-onboarding-input\",\n placeholder: \"+1 555 000 0000\",\n autocomplete: \"tel\",\n }) as HTMLInputElement;\n\n const messageInput = el(\"textarea\", {\n id: \"nodii-message\",\n name: \"message\",\n class: \"nodii-onboarding-textarea\",\n placeholder: \"How can we help?\",\n maxlength: \"4000\",\n rows: \"4\",\n }) as HTMLTextAreaElement;\n\n const serverErrorEl = el(\"div\", {\n class: \"nodii-onboarding-server-error\",\n role: \"alert\",\n \"aria-live\": \"assertive\",\n style: \"display:none\",\n });\n\n const successEl = el(\n \"div\",\n {\n class: \"nodii-onboarding-success\",\n role: \"status\",\n style: \"display:none\",\n },\n [options.successMessage ?? \"Thank you! We'll be in touch shortly.\"],\n );\n\n const submitBtn = el(\n \"button\",\n {\n type: \"submit\",\n class: \"nodii-onboarding-submit-btn\",\n },\n [options.submitLabel ?? \"Get in touch\"],\n );\n\n const recaptchaNotice = el(\n \"p\",\n { class: \"nodii-onboarding-recaptcha-notice\" },\n [\n \"Protected by reCAPTCHA. \",\n Object.assign(\n el(\"a\", {\n href: \"https://policies.google.com/privacy\",\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n }),\n { textContent: \"Privacy\" },\n ),\n \" & \",\n Object.assign(\n el(\"a\", {\n href: \"https://policies.google.com/terms\",\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n }),\n { textContent: \"Terms\" },\n ),\n ],\n );\n\n const form = el(\"form\", {\n novalidate: \"true\",\n \"aria-label\": \"Contact us\",\n });\n\n form.appendChild(createFieldEl(\"nodii-name\", \"Name\", nameInput, true));\n form.appendChild(createFieldEl(\"nodii-email\", \"Email\", emailInput, true));\n form.appendChild(\n createFieldEl(\"nodii-phone\", \"Phone (optional)\", phoneInput, false),\n );\n form.appendChild(\n createFieldEl(\"nodii-message\", \"Message (optional)\", messageInput, false),\n );\n form.appendChild(serverErrorEl);\n form.appendChild(submitBtn);\n form.appendChild(recaptchaNotice);\n\n wrapper.appendChild(successEl);\n wrapper.appendChild(form);\n host.appendChild(wrapper);\n\n // --- Wire input events ---\n nameInput.addEventListener(\"input\", () => {\n formControl.setValue(\"name\", nameInput.value);\n });\n emailInput.addEventListener(\"input\", () => {\n formControl.setValue(\"email\", emailInput.value);\n });\n phoneInput.addEventListener(\"input\", () => {\n formControl.setValue(\"phone\", phoneInput.value || undefined);\n });\n messageInput.addEventListener(\"input\", () => {\n formControl.setValue(\"message\", messageInput.value || undefined);\n });\n\n const submitLabel = options.submitLabel ?? \"Get in touch\";\n\n // Render the submit button content via DOM nodes ONLY — never innerHTML.\n // options.submitLabel may be integrator/CMS-influenced text; text nodes\n // guarantee it can never be interpreted as markup.\n function renderSubmitButton(submitting: boolean): void {\n while (submitBtn.firstChild) {\n submitBtn.removeChild(submitBtn.firstChild);\n }\n if (submitting) {\n const spinner = document.createElement(\"span\");\n spinner.className = \"nodii-onboarding-spinner\";\n submitBtn.appendChild(spinner);\n submitBtn.appendChild(document.createTextNode(\"Sending…\"));\n } else {\n submitBtn.appendChild(document.createTextNode(submitLabel));\n }\n }\n\n // Subscribe to state changes\n const unsubscribe = formControl.subscribe((state) => {\n // Update submit button state\n submitBtn.disabled = state.status === \"submitting\";\n renderSubmitButton(state.status === \"submitting\");\n\n // Apply field errors\n applyErrors(wrapper, state.errors);\n\n // Server error\n if (state.serverError) {\n serverErrorEl.textContent = state.serverError;\n serverErrorEl.style.display = \"\";\n } else {\n serverErrorEl.style.display = \"none\";\n }\n\n // Success state\n if (state.status === \"success\") {\n successEl.style.display = \"\";\n form.style.display = \"none\";\n }\n });\n\n // --- Submit handler ---\n //\n // Idempotency-Key discipline (mirrors the server's D538 payload-match\n // guard — same key + different payload is INVALID_ARGUMENT server-side):\n // - The key is stable across RETRIES of the SAME payload (fingerprint\n // of the outgoing body minus botToken).\n // - If the user EDITS any field after a failed attempt, the fingerprint\n // changes → a NEW key is minted: an edited resubmission is a NEW\n // logical submission, not a retry.\n // - Cleared on success and on reset().\n let idempotencyKey: string | null = null;\n let lastFingerprint: string | null = null;\n\n form.addEventListener(\"submit\", async (event: Event) => {\n event.preventDefault();\n\n // Sync inputs to state\n formControl.setValue(\"name\", nameInput.value);\n formControl.setValue(\"email\", emailInput.value);\n formControl.setValue(\"phone\", phoneInput.value || undefined);\n formControl.setValue(\"message\", messageInput.value || undefined);\n\n const valid = formControl.validate();\n if (!valid) return;\n\n formControl.setSubmitting();\n\n const values = formControl.getState().values as ContactFormValues;\n\n // Key management per the discipline above.\n const fingerprint = computePayloadFingerprint(values);\n if (idempotencyKey === null || fingerprint !== lastFingerprint) {\n idempotencyKey = generateIdempotencyKey();\n lastFingerprint = fingerprint;\n }\n\n // Acquire the FIRST token up front so a mount-time reCAPTCHA failure\n // surfaces a clear message before any HTTP. On retries, submitLead mints\n // a FRESH token per attempt via this same provider (tokens are\n // single-use — reusing one after a 5xx would 403). Bounded by timeoutMs.\n let firstToken: string | undefined;\n if (options.siteKey) {\n try {\n firstToken = await executeRecaptcha(options.siteKey, \"contact_submit\", {\n timeoutMs: options.timeoutMs,\n });\n } catch (recaptchaErr) {\n formControl.setError(\n \"Could not load bot protection. Please try again.\",\n );\n options.onError?.(recaptchaErr);\n return;\n }\n }\n let usedFirst = false;\n const tokenProvider = async (): Promise<string> => {\n if (!usedFirst) {\n usedFirst = true;\n return firstToken!;\n }\n return executeRecaptcha(options.siteKey!, \"contact_submit\", {\n timeoutMs: options.timeoutMs,\n });\n };\n\n try {\n await submitLead(values, {\n baseUrl: options.baseUrl,\n ...(options.siteKey ? { botToken: tokenProvider } : {}),\n idempotencyKey,\n fetch: options.fetch,\n timeoutMs: options.timeoutMs,\n });\n // Clear for the next logical submission.\n idempotencyKey = null;\n lastFingerprint = null;\n formControl.setSuccess();\n options.onSuccess?.();\n } catch (err) {\n if (err instanceof OnboardingBotChallengeError) {\n formControl.setError(\n \"Bot protection check failed. Please refresh the page and try again.\",\n );\n options.onError?.(err);\n } else if (err instanceof OnboardingRateLimitError) {\n const msg =\n err.retryAfterSeconds !== null\n ? `Too many requests. Please wait ${err.retryAfterSeconds}s.`\n : \"Too many requests. Please wait a moment.\";\n formControl.setError(msg);\n options.onError?.(err);\n } else {\n formControl.setError(\n \"Something went wrong. Please try again in a moment.\",\n );\n options.onError?.(err);\n }\n }\n });\n\n return {\n unmount() {\n unsubscribe();\n host.removeChild(wrapper);\n },\n reset() {\n idempotencyKey = null;\n lastFingerprint = null;\n formControl.reset();\n form.style.display = \"\";\n successEl.style.display = \"none\";\n nameInput.value = \"\";\n emailInput.value = \"\";\n phoneInput.value = \"\";\n messageInput.value = \"\";\n },\n };\n}\n","/**\n * Default ConsentPack step components (D543 §5) — built ON the headless\n * ConsentController (dogfooding it). This is the batteries-included layer for\n * Nodii's own turnkey signup + tenants who want a default UI. Advanced tenants\n * skip this entirely and bind their OWN rendering to the headless controller\n * (see @nodii/onboarding/consent) — the TanStack model.\n *\n * NO IFRAME. A cross-origin iframe cannot report scroll position, so it can't\n * drive `scroll_then_accept`. The default document VIEWER\n * (@nodii/onboarding/viewer, lazy-imported) renders content INLINE, SAME-ORIGIN\n * (HTML→DOMPurify, markdown→marked, PDF→PDF.js) in a scroll `<div>` whose real\n * scroll events feed reportScrollProgress — so scroll-to-end is genuinely\n * detected. The scroll box reports progress ONLY after real content is present.\n *\n * Gate affordance per acceptance level:\n * - checkbox → a lightweight preview link (no gate; accept enabled).\n * - scroll_then_accept → the viewer renders the doc inline; scroll-to-end\n * drives the gate.\n * - open_then_accept → an open-in-a-new-tab control; a REAL open marks\n * `opened` (the open IS the gate).\n *\n * COMPLIANCE (P0 — never fabricate consent): if the viewer MODULE fails to load\n * (CDN chunk 404 / offline) for a scroll_then_accept doc, the gate stays\n * UNSATISFIABLE — a clear error + Retry is shown and accept remains DISABLED.\n * We NEVER satisfy a scroll gate on a click; an \"open in a new tab\" link on the\n * error is INFORMATIONAL only and does not unlock the gate. (The viewer's own\n * fetch/render failures follow the same rule; see @nodii/onboarding/viewer.)\n *\n * Theming rides the existing --nodii-onboarding-* CSS custom properties; all\n * classes are scoped under `.nodii-onboarding-widget`. Full-width, generous\n * spacing (operator directive) via styles.ts.\n *\n * a11y: every accept checkbox has a `<label for>` pointing at its real id; the\n * id token derives from the doc's stable key (docType | custom:<key>),\n * sanitized to an id-safe token and CSS-escaped in every selector.\n */\n\nimport type {\n ConsentController,\n ConsentDocState,\n ConsentState,\n} from \"../consent/controller.js\";\nimport { SCROLL_END_THRESHOLD } from \"../consent/controller.js\";\nimport { cssEscape, idSelector } from \"./dom-utils.js\";\n\n/** Prefix for every consent DOM id (kept distinct from field/account ids). */\nconst CONSENT_ID_PREFIX = \"nodii-consent-doc-\";\n\n/** Render-time options for the default consent step. */\nexport interface ConsentStepRenderOptions {\n /** Injectable fetch for doc-content load (defaults to global). */\n fetch?: typeof globalThis.fetch;\n timeoutMs?: number;\n /**\n * Injectable viewer-module importer (defaults to the real dynamic\n * `import(\"../viewer/render.js\")`). Exposed so a consumer can control code-\n * splitting AND so tests can drive the module-load-FAILURE branch WITHOUT\n * `mock.module` (which leaks across bun tests). Must resolve to an object\n * exposing `renderConsentDocument`; rejecting simulates a chunk-load failure.\n */\n importViewer?: () => Promise<typeof import(\"../viewer/render.js\")>;\n}\n\nfunction el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs: Record<string, string> = {},\n children: Array<HTMLElement | Text | string> = [],\n): HTMLElementTagNameMap[K] {\n const element = document.createElement(tag);\n for (const [key, value] of Object.entries(attrs)) {\n element.setAttribute(key, value);\n }\n for (const child of children) {\n if (typeof child === \"string\") {\n element.appendChild(document.createTextNode(child));\n } else {\n element.appendChild(child);\n }\n }\n return element;\n}\n\n/**\n * Turn a consent doc's stable key into a DOM-id-safe token. `doc_type` is a\n * fixed enum (safe); a custom key arrives as `custom:<key>` — the `:` and any\n * residual metachar are replaced so the raw token is valid inside an id AND\n * inside a `#id` selector. (The key is already `[A-Za-z0-9_-]+` past the `:`\n * per model.ts; this only neutralizes the `custom:` prefix separator.)\n */\nexport function consentDocElementId(key: string): string {\n return `${CONSENT_ID_PREFIX}${key.replace(/[^A-Za-z0-9_-]/g, \"-\")}`;\n}\n\n/** Build the accept-checkbox row for one document. */\nfunction buildAcceptRow(\n control: ConsentController,\n doc: ConsentDocState,\n): { row: HTMLElement; errorEl: HTMLElement } {\n const id = consentDocElementId(doc.key);\n const checkbox = el(\"input\", {\n type: \"checkbox\",\n id,\n class: \"nodii-onboarding-consent-accept\",\n }) as HTMLInputElement;\n checkbox.checked = doc.accepted;\n checkbox.disabled = !doc.gateSatisfied;\n checkbox.addEventListener(\"change\", () => {\n // The controller REFUSES acceptance when the gate is unsatisfied; reflect\n // the authoritative post-mutation state back into the DOM so a disabled-\n // bypass (e.g. programmatic .checked) cannot desync the UI from consent.\n control.setAccepted(doc.key, checkbox.checked);\n checkbox.checked =\n control.getState().documents.find((d) => d.key === doc.key)?.accepted ??\n false;\n });\n\n const labelText =\n doc.acceptanceLevel === \"checkbox\"\n ? `I accept the ${doc.doc.title}`\n : `I have reviewed and accept the ${doc.doc.title}`;\n const label = el(\n \"label\",\n { for: id, class: \"nodii-onboarding-consent-accept-label\" },\n [labelText],\n );\n if (doc.required) {\n label.appendChild(\n el(\"span\", { class: \"nodii-onboarding-consent-required\" }, [\" *\"]),\n );\n }\n\n const row = el(\"div\", { class: \"nodii-onboarding-consent-accept-row\" }, [\n checkbox,\n label,\n ]);\n const errorEl = el(\"div\", {\n class: \"nodii-onboarding-field-error nodii-onboarding-consent-error\",\n id: `${id}-error`,\n role: \"alert\",\n \"aria-live\": \"polite\",\n });\n return { row, errorEl };\n}\n\n/**\n * An open-in-tab affordance for an `open_then_accept` doc — opening the doc in\n * a new tab IS the gate for this level, so marking `opened` on a REAL open is\n * legitimate. A native <a target=\"_blank\"> navigates on click and on Enter\n * (keyboard activation). We do NOT bind Space — Space does not activate an\n * anchor (no navigation → no real open → marking opened would fabricate).\n */\nfunction buildOpenAffordance(\n control: ConsentController,\n doc: ConsentDocState,\n): HTMLElement {\n const id = consentDocElementId(doc.key);\n const openLink = el(\n \"a\",\n {\n class: \"nodii-onboarding-consent-open\",\n id: `${id}-open`,\n href: doc.doc.downloadUrl,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n [`Open ${doc.doc.title}`],\n );\n const markOpened = (): void => control.markOpened(doc.key);\n openLink.addEventListener(\"click\", markOpened);\n openLink.addEventListener(\"keydown\", (event) => {\n if ((event as KeyboardEvent).key === \"Enter\") markOpened();\n });\n return el(\"div\", { class: \"nodii-onboarding-consent-open-row\" }, [openLink]);\n}\n\n/**\n * Build the gate affordance for one document.\n *\n * - open_then_accept → an open-in-tab control (marks opened).\n * - checkbox → a lightweight preview link (no gate).\n * - scroll_then_accept → an inline document container populated by the DEFAULT\n * VIEWER (@nodii/onboarding/viewer), loaded via a DYNAMIC import() so the\n * base widget bundle never statically pulls DOMPurify / marked / pdfjs. The\n * viewer renders the doc inline same-origin (HTML→DOMPurify, md→marked, PDF→\n * PDF.js) and wires the scroll container's scroll-to-end to the controller\n * so the gate is real. COMPLIANCE (P0): if the viewer MODULE fails to load,\n * the scroll gate stays UNSATISFIABLE — a clear error + Retry is shown and\n * accept stays DISABLED; we NEVER unlock a scroll gate on a click. (The\n * viewer's own fetch/render failures follow the same rule.)\n */\nfunction buildGateAffordance(\n control: ConsentController,\n doc: ConsentDocState,\n opts: ConsentStepRenderOptions,\n): HTMLElement {\n const id = consentDocElementId(doc.key);\n\n if (doc.acceptanceLevel === \"open_then_accept\") {\n return buildOpenAffordance(control, doc);\n }\n\n if (doc.acceptanceLevel === \"checkbox\") {\n return el(\"div\", { class: \"nodii-onboarding-consent-preview-row\" }, [\n el(\n \"a\",\n {\n class: \"nodii-onboarding-consent-preview\",\n id: `${id}-preview`,\n href: doc.doc.downloadUrl,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n [`View ${doc.doc.title}`],\n ),\n ]);\n }\n\n // scroll_then_accept: delegate to the default viewer (dynamically imported).\n const container = el(\"div\", {\n class: \"nodii-onboarding-consent-gate\",\n id: `${id}-gate`,\n });\n container.appendChild(\n el(\"div\", { class: \"nodii-onboarding-consent-doc-loading\" }, [\n \"Loading document…\",\n ]),\n );\n\n const importViewer =\n opts.importViewer ?? (() => import(\"../viewer/render.js\"));\n const loadViewer = (): void => {\n void (async () => {\n try {\n const { renderConsentDocument } = await importViewer();\n await renderConsentDocument(container, doc.doc, control, {\n consentKey: doc.key,\n fetch: opts.fetch,\n timeoutMs: opts.timeoutMs,\n });\n } catch {\n // COMPLIANCE-CRITICAL (P0): the viewer MODULE itself failed to load\n // (CDN chunk 404, offline). A scroll_then_accept doc cannot be\n // scrolled → its gate stays UNSATISFIABLE. We MUST NOT satisfy the\n // scroll gate on a click — that would fabricate scrolled_to_end.\n // Render a clear error + Retry (re-attempts the import); accept stays\n // disabled. An informational open link does NOT satisfy the gate.\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n const wrap = el(\"div\", {\n class: \"nodii-onboarding-consent-unrenderable\",\n role: \"alert\",\n });\n wrap.appendChild(\n el(\n \"p\",\n {\n // DISTINCT id (NOT `${id}-error`): buildAcceptRow already owns\n // `${id}-error`, and updateConsentStep's querySelector would match\n // THIS paragraph first and blank it on the next state change,\n // silently wiping the compliance message. A unique id keeps this\n // load-failure error persistent (P1b).\n class:\n \"nodii-onboarding-field-error nodii-onboarding-consent-error\",\n id: `${id}-load-error`,\n },\n [\n `“${doc.doc.title}” could not be loaded, so it cannot be accepted yet. Please retry.`,\n ],\n ),\n );\n const retry = el(\n \"button\",\n { type: \"button\", class: \"nodii-onboarding-consent-retry\" },\n [\"Retry loading document\"],\n );\n retry.addEventListener(\"click\", loadViewer);\n wrap.appendChild(retry);\n // Informational only — opening in a new tab does NOT satisfy scroll.\n wrap.appendChild(\n el(\n \"a\",\n {\n class: \"nodii-onboarding-consent-open\",\n href: doc.doc.downloadUrl,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n [`Open ${doc.doc.title} in a new tab`],\n ),\n );\n container.appendChild(wrap);\n }\n })();\n };\n loadViewer();\n\n return container;\n}\n\n/** Build one full-width consent card for a document. */\nfunction buildConsentCard(\n control: ConsentController,\n doc: ConsentDocState,\n stale: boolean,\n opts: ConsentStepRenderOptions,\n): HTMLElement {\n const card = el(\"div\", {\n class: `nodii-onboarding-consent-card${stale ? \" is-stale\" : \"\"}`,\n \"data-consent-key\": doc.key,\n });\n card.appendChild(\n el(\"h4\", { class: \"nodii-onboarding-consent-title\" }, [doc.doc.title]),\n );\n if (stale) {\n card.appendChild(\n el(\n \"div\",\n { class: \"nodii-onboarding-consent-stale-tag\", role: \"status\" },\n [\"Updated — please review and re-accept.\"],\n ),\n );\n }\n card.appendChild(buildGateAffordance(control, doc, opts));\n const { row, errorEl } = buildAcceptRow(control, doc);\n card.appendChild(row);\n card.appendChild(errorEl);\n return card;\n}\n\n/**\n * Render (or re-render) the consent stage into a host container from the given\n * consent state. Full re-render (the doc set is small); disabled/checked/error\n * state is refreshed in place via updateConsentStep so scroll position and\n * inline doc content are not lost on unrelated state changes.\n */\nexport function renderConsentStep(\n host: HTMLElement,\n control: ConsentController,\n state: ConsentState,\n staleKeys: string[] = [],\n opts: ConsentStepRenderOptions = {},\n): void {\n while (host.firstChild) host.removeChild(host.firstChild);\n const staleSet = new Set(staleKeys);\n\n host.appendChild(\n el(\"h3\", { class: \"nodii-onboarding-stage-title\" }, [\n \"Review & accept documents\",\n ]),\n );\n host.appendChild(\n el(\"p\", { class: \"nodii-onboarding-consent-intro\" }, [\n \"Please review each document below and accept to continue.\",\n ]),\n );\n\n for (const doc of state.documents) {\n host.appendChild(\n buildConsentCard(control, doc, staleSet.has(doc.key), opts),\n );\n }\n}\n\n/**\n * Refresh the consent cards' disabled/checked/error state in place (no full\n * re-render) — called on every stepper state change so gate unlocks and\n * live-clearing errors reflect immediately without losing scroll position or\n * re-fetching inline doc content.\n */\nexport function updateConsentStep(\n host: HTMLElement,\n state: ConsentState,\n consentErrors: Array<{ path: string; message: string }>,\n): void {\n const errorByKey = new Map(consentErrors.map((e) => [e.path, e.message]));\n for (const doc of state.documents) {\n const id = consentDocElementId(doc.key);\n const checkbox = host.querySelector(\n idSelector(id),\n ) as HTMLInputElement | null;\n if (checkbox) {\n checkbox.disabled = !doc.gateSatisfied;\n checkbox.checked = doc.accepted;\n }\n const errorNode = host.querySelector(idSelector(`${id}-error`));\n if (errorNode) errorNode.textContent = errorByKey.get(doc.key) ?? \"\";\n const card = host.querySelector(\n `[data-consent-key=\"${cssEscape(doc.key)}\"]`,\n );\n if (card) {\n if (errorByKey.has(doc.key)) card.classList.add(\"has-error\");\n else card.classList.remove(\"has-error\");\n }\n }\n}\n\n/** Re-export for consumers wiring their own scroll handler to the controller. */\nexport { SCROLL_END_THRESHOLD };\n","/// <reference lib=\"dom\" />\n/// <reference lib=\"dom.iterable\" />\n/**\n * Default vanilla-TS dynamic signup stepper widget (D540 Phase 2).\n *\n * Mount flow:\n * 1. Fetch + validate the spec (GET /api/v1/public/onboarding/spec);\n * the reCAPTCHA siteKey comes FROM THE SPEC (botChallenge.siteKey) —\n * the mount-option siteKey is only an override/fallback.\n * 2. Build the headless stepper from spec.forms.signup.steps.\n * 3. Render the current step's fields per descriptor type; Back/Next\n * navigate with per-step validation.\n * 4. The FINAL step carries the account section (credentials + consent\n * clickwrap) and the submit button.\n * 5. Submit: validateAll → payload-fingerprint key management (same\n * D538 discipline as the contact widget) → reCAPTCHA token →\n * submitSignup.\n * 6. 409 spec_stale: refetch the spec, applyNewSpec (drops removed\n * fields, re-validates), show a \"form updated — please review\"\n * banner. The SDK NEVER auto-resubmits a stale submission.\n */\n\nimport {\n fetchOnboardingSpec,\n OnboardingSpecCache,\n defaultSpecCache,\n diffSpecFields,\n type OnboardingSpec,\n} from \"../spec/index.js\";\nimport type { SpecField } from \"../spec/model.js\";\nimport {\n createSignupStepper,\n type SignupStepperControl,\n type SignupStepperState,\n} from \"../dynamic/stepper.js\";\nimport { optionValue } from \"../dynamic/derive.js\";\nimport {\n submitSignup,\n computeSignupFingerprint,\n type SignupSubmitResult,\n} from \"../submit/signup-client.js\";\nimport { generateIdempotencyKey } from \"../submit/client.js\";\nimport {\n OnboardingBotChallengeError,\n OnboardingConsentIncompleteError,\n OnboardingConsentStaleError,\n OnboardingRateLimitError,\n OnboardingSpecStaleError,\n} from \"../submit/errors.js\";\nimport { executeRecaptcha } from \"../recaptcha/loader.js\";\nimport { idSelector } from \"./dom-utils.js\";\nimport { injectWidgetStyles } from \"./styles.js\";\nimport { renderConsentStep, updateConsentStep } from \"./consent-step.js\";\nimport type { MountedWidget } from \"./contact-form.js\";\n\nexport interface SignupFormMountOptions {\n /**\n * The onboarder identifier — the CLIENT-side spec-cache key\n * (D540 §3 `(onboarder, specVersion)`). NOT transmitted: per LOCKED\n * D536, onboarder trust/scoping is host-derived at the edge.\n */\n onboarder: string;\n baseUrl: string;\n /**\n * OPTIONAL siteKey override. Normally the widget uses the siteKey the\n * spec serves (botChallenge.siteKey, D537/D540); pass this only for\n * environments where the spec cannot carry it yet.\n */\n siteKey?: string;\n form: \"signup\";\n onSuccess?: (result: SignupSubmitResult) => void;\n onError?: (error: unknown) => void;\n /** Called after the spec loads and the stepper renders. */\n onReady?: (spec: OnboardingSpec) => void;\n fetch?: typeof globalThis.fetch;\n /**\n * Per-request timeout in ms (default 15s), applied to the boot spec fetch,\n * the reCAPTCHA execute(), the submit POST, and the 409 refetch — so a hung\n * dependency never leaves \"Loading signup form…\"/\"Sending…\" stuck.\n */\n timeoutMs?: number;\n submitLabel?: string;\n tosUrl?: string;\n privacyUrl?: string;\n /** Spec cache override (defaults to the module-level cache). */\n cache?: OnboardingSpecCache;\n}\n\nconst STAGE_TITLES: Record<string, string> = {\n lead: \"About you\",\n prospect: \"Your business\",\n activation: \"Choose your services\",\n};\n\nfunction el<K extends keyof HTMLElementTagNameMap>(\n tag: K,\n attrs: Record<string, string> = {},\n children: Array<HTMLElement | Text | string> = [],\n): HTMLElementTagNameMap[K] {\n const element = document.createElement(tag);\n for (const [key, value] of Object.entries(attrs)) {\n element.setAttribute(key, value);\n }\n for (const child of children) {\n if (typeof child === \"string\") {\n element.appendChild(document.createTextNode(child));\n } else {\n element.appendChild(child);\n }\n }\n return element;\n}\n\nfunction optionLabel(option: unknown): string {\n if (option !== null && typeof option === \"object\") {\n const o = option as Record<string, unknown>;\n if (typeof o[\"label\"] === \"string\") return o[\"label\"];\n }\n return optionValue(option);\n}\n\n/** Build the input element for one spec field descriptor. */\nfunction buildFieldInput(\n field: SpecField,\n currentValue: unknown,\n onChange: (value: unknown) => void,\n): HTMLElement {\n const id = `nodii-f-${field.key}`;\n\n switch (field.type) {\n case \"textarea\": {\n const input = el(\"textarea\", {\n id,\n class: \"nodii-onboarding-textarea\",\n rows: \"4\",\n }) as HTMLTextAreaElement;\n if (typeof currentValue === \"string\") input.value = currentValue;\n input.addEventListener(\"input\", () => onChange(input.value));\n return input;\n }\n case \"checkbox\":\n case \"boolean\": {\n const input = el(\"input\", {\n type: \"checkbox\",\n id,\n }) as HTMLInputElement;\n input.checked = currentValue === true;\n input.addEventListener(\"change\", () => onChange(input.checked));\n return input;\n }\n case \"select\":\n case \"radio\": {\n const select = el(\"select\", {\n id,\n class: \"nodii-onboarding-input\",\n }) as HTMLSelectElement;\n select.appendChild(el(\"option\", { value: \"\" }, [\"— select —\"]));\n for (const opt of field.options ?? []) {\n const value = optionValue(opt);\n const optionEl = el(\"option\", { value }, [optionLabel(opt)]);\n select.appendChild(optionEl);\n }\n if (typeof currentValue === \"string\") select.value = currentValue;\n select.addEventListener(\"change\", () => onChange(select.value));\n return select;\n }\n case \"multiselect\": {\n const select = el(\"select\", {\n id,\n class: \"nodii-onboarding-input\",\n multiple: \"multiple\",\n }) as HTMLSelectElement;\n const current = Array.isArray(currentValue)\n ? currentValue.map(String)\n : [];\n for (const opt of field.options ?? []) {\n const value = optionValue(opt);\n const optionEl = el(\"option\", { value }, [\n optionLabel(opt),\n ]) as HTMLOptionElement;\n if (current.includes(value)) optionEl.selected = true;\n select.appendChild(optionEl);\n }\n select.addEventListener(\"change\", () => {\n const values: string[] = [];\n for (const o of Array.from(select.options)) {\n if (o.selected && o.value !== \"\") values.push(o.value);\n }\n onChange(values);\n });\n return select;\n }\n default: {\n // text | email | tel | number | date | unknown → typed <input>\n const typeAttr =\n field.type === \"email\" ||\n field.type === \"tel\" ||\n field.type === \"number\" ||\n field.type === \"date\"\n ? field.type\n : \"text\";\n const input = el(\"input\", {\n type: typeAttr,\n id,\n class: \"nodii-onboarding-input\",\n }) as HTMLInputElement;\n if (typeof currentValue === \"string\") input.value = currentValue;\n if (typeof currentValue === \"number\") input.value = String(currentValue);\n input.addEventListener(\"input\", () => onChange(input.value));\n return input;\n }\n }\n}\n\n/**\n * Build a labelled field row. The label `for`, the input id, and the error\n * element id must ALL agree so click-to-focus and screen-reader association\n * work. Callers whose input id is NOT `nodii-f-<key>` (the account section,\n * whose inputs are `nodii-account-*`) pass `idOverride` so the label points\n * at the REAL input — never a dangling id patched up post-hoc.\n */\nfunction fieldRow(\n field: SpecField,\n input: HTMLElement,\n idOverride?: string,\n): HTMLElement {\n const id = idOverride ?? `nodii-f-${field.key}`;\n const labelEl = el(\n \"label\",\n {\n for: id,\n class: `nodii-onboarding-label${field.required ? \" required\" : \"\"}`,\n },\n [field.label],\n );\n const errorEl = el(\"div\", {\n class: \"nodii-onboarding-field-error\",\n id: `${id}-error`,\n role: \"alert\",\n \"aria-live\": \"polite\",\n });\n return el(\"div\", { class: \"nodii-onboarding-field\" }, [\n labelEl,\n input,\n errorEl,\n ]);\n}\n\n/**\n * Mount the dynamic signup stepper into a host element.\n * Returns synchronously; the spec loads in the background (loading state\n * rendered meanwhile; onReady fires when interactive).\n */\nexport function mountSignupForm(\n host: HTMLElement,\n options: SignupFormMountOptions,\n): MountedWidget {\n injectWidgetStyles();\n\n const wrapper = el(\"div\", { class: \"nodii-onboarding-widget\" });\n const loadingEl = el(\"div\", { class: \"nodii-onboarding-loading\" }, [\n \"Loading signup form…\",\n ]);\n wrapper.appendChild(loadingEl);\n host.appendChild(wrapper);\n\n const cache = options.cache ?? defaultSpecCache;\n let stepper: SignupStepperControl | null = null;\n let unsubscribe: (() => void) | null = null;\n let unmounted = false;\n let siteKey = options.siteKey ?? \"\";\n let idempotencyKey: string | null = null;\n let lastFingerprint: string | null = null;\n let renderedStepIndex = -1;\n let renderedStale = false;\n // Tracks the last-rendered consentStale flag so a consent_stale swap forces\n // a full step re-render (like specStale) — the cards must re-render with the\n // \"Updated — please review\" tags and cleared acceptance.\n let renderedConsentStale = false;\n // The (onboarder, specVersion) currently driving the form — used to READ\n // the prior cached version back out on a 409 and diff what changed.\n let currentSpecVersion: string | null = null;\n let staleDiffSummary = \"\";\n\n // DOM regions (populated by renderShell)\n const stepArea = el(\"div\", {});\n const staleBanner = el(\"div\", {\n class: \"nodii-onboarding-stale-banner\",\n role: \"alert\",\n style: \"display:none\",\n });\n const serverErrorEl = el(\"div\", {\n class: \"nodii-onboarding-server-error\",\n role: \"alert\",\n \"aria-live\": \"assertive\",\n style: \"display:none\",\n });\n const successEl = el(\"div\", {\n class: \"nodii-onboarding-success\",\n role: \"status\",\n style: \"display:none\",\n });\n const stepsIndicator = el(\"div\", { class: \"nodii-onboarding-steps\" });\n const form = el(\"form\", { novalidate: \"true\", \"aria-label\": \"Sign up\" });\n\n function setFieldErrorsInPlace(\n container: HTMLElement,\n errors: Array<{ path: string; message: string }>,\n idPrefix: (path: string) => string,\n ): void {\n for (const errEl of container.querySelectorAll(\n \".nodii-onboarding-field-error\",\n )) {\n errEl.textContent = \"\";\n }\n for (const marked of container.querySelectorAll(\".has-error\")) {\n marked.classList.remove(\"has-error\");\n }\n for (const err of errors) {\n const id = idPrefix(err.path);\n // CSS-escape: id derives from spec field keys (err.path).\n const errorNode = container.querySelector(idSelector(`${id}-error`));\n if (errorNode) errorNode.textContent = err.message;\n const inputNode = container.querySelector(idSelector(id));\n if (inputNode) inputNode.classList.add(\"has-error\");\n }\n }\n\n function accountIdOf(path: string): string {\n if (path === \"email\") return \"nodii-account-email\";\n if (path === \"displayName\") return \"nodii-account-display-name\";\n if (path === \"tosAccepted\") return \"nodii-consent-tos\";\n if (path === \"privacyAccepted\") return \"nodii-consent-privacy\";\n return `nodii-account-${path}`;\n }\n\n function renderStepsIndicator(state: SignupStepperState): void {\n while (stepsIndicator.firstChild) {\n stepsIndicator.removeChild(stepsIndicator.firstChild);\n }\n for (let i = 0; i < state.stepCount; i++) {\n stepsIndicator.appendChild(\n el(\"div\", {\n class: `nodii-onboarding-step-dot${i <= state.stepIndex ? \" active\" : \"\"}`,\n }),\n );\n }\n }\n\n function renderAccountSection(\n control: SignupStepperControl,\n state: SignupStepperState,\n ): HTMLElement {\n const section = el(\"div\", { class: \"nodii-onboarding-account-section\" });\n\n const emailInput = el(\"input\", {\n type: \"email\",\n id: \"nodii-account-email\",\n class: \"nodii-onboarding-input\",\n autocomplete: \"email\",\n }) as HTMLInputElement;\n emailInput.value = state.credentials.email;\n emailInput.addEventListener(\"input\", () =>\n control.setCredentials({ email: emailInput.value }),\n );\n section.appendChild(\n fieldRow(\n {\n key: \"account-email\",\n type: \"email\",\n label: \"Account email\",\n required: true,\n },\n emailInput,\n \"nodii-account-email\", // label for + error id match the real input id\n ),\n );\n\n const displayNameInput = el(\"input\", {\n type: \"text\",\n id: \"nodii-account-display-name\",\n class: \"nodii-onboarding-input\",\n autocomplete: \"name\",\n maxlength: \"200\",\n }) as HTMLInputElement;\n displayNameInput.value = state.credentials.displayName;\n displayNameInput.addEventListener(\"input\", () =>\n control.setCredentials({ displayName: displayNameInput.value }),\n );\n section.appendChild(\n fieldRow(\n {\n key: \"account-display-name\",\n type: \"text\",\n label: \"Your name\",\n required: true,\n },\n displayNameInput,\n \"nodii-account-display-name\",\n ),\n );\n\n for (const [key, label, autocomplete] of [\n [\"organisationName\", \"Organisation name\", \"organization\"],\n [\"subdomain\", \"Workspace subdomain\", \"off\"],\n ] as const) {\n const input = el(\"input\", {\n type: \"text\",\n id: `nodii-account-${key}`,\n class: \"nodii-onboarding-input\",\n autocomplete,\n maxlength: key === \"subdomain\" ? \"63\" : \"200\",\n }) as HTMLInputElement;\n input.value = state.credentials[key];\n input.addEventListener(\"input\", () =>\n control.setCredentials({ [key]: input.value }),\n );\n section.appendChild(\n fieldRow(\n { key: `account-${key}`, type: \"text\", label, required: true },\n input,\n `nodii-account-${key}`,\n ),\n );\n }\n\n const tosCheckbox = el(\"input\", {\n type: \"checkbox\",\n id: \"nodii-consent-tos\",\n }) as HTMLInputElement;\n tosCheckbox.checked = state.consent.tosAccepted;\n tosCheckbox.addEventListener(\"change\", () =>\n control.setConsent({ tosAccepted: tosCheckbox.checked }),\n );\n const tosLabelChildren: Array<HTMLElement | string> = [\"I accept the \"];\n if (options.tosUrl) {\n tosLabelChildren.push(\n el(\n \"a\",\n {\n href: options.tosUrl,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n [\"Terms of Service\"],\n ),\n );\n } else {\n tosLabelChildren.push(\"Terms of Service\");\n }\n section.appendChild(\n el(\"div\", { class: \"nodii-onboarding-consent-row\" }, [\n tosCheckbox,\n el(\"label\", { for: \"nodii-consent-tos\" }, tosLabelChildren),\n ]),\n );\n section.appendChild(\n el(\"div\", {\n class: \"nodii-onboarding-field-error\",\n id: \"nodii-consent-tos-error\",\n role: \"alert\",\n }),\n );\n\n const privacyCheckbox = el(\"input\", {\n type: \"checkbox\",\n id: \"nodii-consent-privacy\",\n }) as HTMLInputElement;\n privacyCheckbox.checked = state.consent.privacyAccepted;\n privacyCheckbox.addEventListener(\"change\", () =>\n control.setConsent({ privacyAccepted: privacyCheckbox.checked }),\n );\n const privacyLabelChildren: Array<HTMLElement | string> = [\"I accept the \"];\n if (options.privacyUrl) {\n privacyLabelChildren.push(\n el(\n \"a\",\n {\n href: options.privacyUrl,\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n },\n [\"Privacy Policy\"],\n ),\n );\n } else {\n privacyLabelChildren.push(\"Privacy Policy\");\n }\n section.appendChild(\n el(\"div\", { class: \"nodii-onboarding-consent-row\" }, [\n privacyCheckbox,\n el(\"label\", { for: \"nodii-consent-privacy\" }, privacyLabelChildren),\n ]),\n );\n section.appendChild(\n el(\"div\", {\n class: \"nodii-onboarding-field-error\",\n id: \"nodii-consent-privacy-error\",\n role: \"alert\",\n }),\n );\n\n return section;\n }\n\n function renderStep(\n control: SignupStepperControl,\n state: SignupStepperState,\n ): void {\n while (stepArea.firstChild) stepArea.removeChild(stepArea.firstChild);\n\n const step = state.currentStep;\n if (step) {\n stepArea.appendChild(\n el(\"h3\", { class: \"nodii-onboarding-stage-title\" }, [\n STAGE_TITLES[step.stage] ?? step.stage,\n ]),\n );\n for (const field of step.fields) {\n const input = buildFieldInput(\n field,\n state.answers[field.key],\n (value) => control.setAnswer(field.key, value),\n );\n stepArea.appendChild(fieldRow(field, input));\n }\n }\n\n const isLast = control.isLastStep();\n if (isLast) {\n // D543 consent stage — full-width consent cards ABOVE the account\n // section on the final step. Rendered only when the spec served a\n // consentPack (control.consent.isEmpty() ⇒ skipped entirely).\n if (!control.consent.isEmpty()) {\n const consentStage = el(\"div\", {\n class: \"nodii-onboarding-consent-stage\",\n });\n renderConsentStep(\n consentStage,\n control.consent,\n state.consentState,\n state.staleConsentKeys,\n { fetch: options.fetch, timeoutMs: options.timeoutMs },\n );\n stepArea.appendChild(consentStage);\n }\n stepArea.appendChild(renderAccountSection(control, state));\n }\n\n const nav = el(\"div\", { class: \"nodii-onboarding-nav\" });\n if (!control.isFirstStep()) {\n const backBtn = el(\n \"button\",\n { type: \"button\", class: \"nodii-onboarding-back-btn\" },\n [\"Back\"],\n );\n backBtn.addEventListener(\"click\", () => control.back());\n nav.appendChild(backBtn);\n }\n const forwardBtn = el(\n \"button\",\n {\n type: isLast ? \"submit\" : \"button\",\n class: \"nodii-onboarding-submit-btn\",\n id: \"nodii-signup-forward\",\n },\n [isLast ? (options.submitLabel ?? \"Create account\") : \"Next\"],\n );\n if (!isLast) {\n forwardBtn.addEventListener(\"click\", () => control.next());\n }\n nav.appendChild(forwardBtn);\n stepArea.appendChild(nav);\n }\n\n async function handleSpecStale(control: SignupStepperControl): Promise<void> {\n // READ the previously-served version back out of the cache (populated on\n // boot under (onboarder, specVersion)) so we can diff it against the\n // refetched spec and tell the user exactly what changed.\n const prior =\n currentSpecVersion !== null\n ? cache.get(options.onboarder, currentSpecVersion)\n : undefined;\n\n const fresh = await fetchOnboardingSpec({\n baseUrl: options.baseUrl,\n onboarder: options.onboarder,\n fetch: options.fetch,\n timeoutMs: options.timeoutMs,\n cache,\n });\n if (unmounted) return;\n\n if (prior) {\n const diff = diffSpecFields(prior, fresh);\n const parts: string[] = [];\n if (diff.added.length) parts.push(`added: ${diff.added.join(\", \")}`);\n if (diff.removed.length)\n parts.push(`removed: ${diff.removed.join(\", \")}`);\n if (diff.changed.length)\n parts.push(`changed: ${diff.changed.join(\", \")}`);\n staleDiffSummary = parts.length ? ` (${parts.join(\"; \")})` : \"\";\n } else {\n staleDiffSummary = \"\";\n }\n\n siteKey = options.siteKey ?? fresh.botChallenge?.siteKey ?? \"\";\n currentSpecVersion = fresh.specVersion;\n control.applyNewSpec(fresh);\n // A stale submission's payload is dead; the next submit is a NEW\n // logical submission against the new specVersion.\n idempotencyKey = null;\n lastFingerprint = null;\n }\n\n /**\n * 409 consent_stale (D543 §4): a required legal doc changed. Refetch the\n * spec and swap ONLY the consentPack — changed docs are reset (re-acceptance\n * required, NEVER auto-accepted). The form fields are left as-is. The user\n * re-accepts and resubmits; the SDK never auto-resubmits.\n */\n async function handleConsentStale(\n control: SignupStepperControl,\n ): Promise<void> {\n const fresh = await fetchOnboardingSpec({\n baseUrl: options.baseUrl,\n onboarder: options.onboarder,\n fetch: options.fetch,\n timeoutMs: options.timeoutMs,\n cache,\n });\n if (unmounted) return;\n\n siteKey = options.siteKey ?? fresh.botChallenge?.siteKey ?? \"\";\n currentSpecVersion = fresh.specVersion;\n control.applyNewConsentPack(fresh);\n // Re-accepting changed docs is a NEW logical submission → rotate the key.\n idempotencyKey = null;\n lastFingerprint = null;\n }\n\n async function handleSubmit(control: SignupStepperControl): Promise<void> {\n if (!control.validateAll()) return;\n control.acknowledgeSpecStale();\n control.setSubmitting();\n\n const body = control.buildSubmitPayload();\n const fingerprint = computeSignupFingerprint(body);\n if (idempotencyKey === null || fingerprint !== lastFingerprint) {\n idempotencyKey = generateIdempotencyKey();\n lastFingerprint = fingerprint;\n }\n\n // First token up front (clear pre-HTTP failure); fresh token per retry\n // attempt via the provider (single-use tokens).\n let firstToken: string | undefined;\n if (siteKey) {\n try {\n firstToken = await executeRecaptcha(siteKey, \"signup_submit\", {\n timeoutMs: options.timeoutMs,\n });\n } catch (recaptchaErr) {\n control.setError(\"Could not load bot protection. Please try again.\");\n options.onError?.(recaptchaErr);\n return;\n }\n }\n let usedFirst = false;\n const tokenProvider = async (): Promise<string> => {\n if (!usedFirst) {\n usedFirst = true;\n return firstToken!;\n }\n return executeRecaptcha(siteKey, \"signup_submit\", {\n timeoutMs: options.timeoutMs,\n });\n };\n\n try {\n const result = await submitSignup(body, {\n baseUrl: options.baseUrl,\n ...(siteKey ? { botToken: tokenProvider } : {}),\n idempotencyKey,\n fetch: options.fetch,\n timeoutMs: options.timeoutMs,\n });\n idempotencyKey = null;\n lastFingerprint = null;\n control.setSuccess(result.terminalStage);\n options.onSuccess?.(result);\n } catch (err) {\n if (err instanceof OnboardingSpecStaleError) {\n try {\n await handleSpecStale(control);\n } catch (refetchErr) {\n control.setError(\n \"The signup form changed and could not be reloaded. Please refresh the page.\",\n );\n options.onError?.(refetchErr);\n return;\n }\n options.onError?.(err);\n } else if (err instanceof OnboardingConsentStaleError) {\n // D543 §4: refetch + swap consentPack; changed docs require\n // re-acceptance. NEVER auto-accept a changed doc, NEVER auto-resubmit.\n try {\n await handleConsentStale(control);\n } catch (refetchErr) {\n control.setError(\n \"The legal documents changed and could not be reloaded. Please refresh the page.\",\n );\n options.onError?.(refetchErr);\n return;\n }\n options.onError?.(err);\n } else if (err instanceof OnboardingConsentIncompleteError) {\n // The server found a required doc missing/unaccepted — route the user\n // back to the consent step. validateAll() will surface the per-doc\n // errors on the next state emit.\n control.validateAll();\n control.setError(\"Please accept all required documents to continue.\");\n options.onError?.(err);\n } else if (err instanceof OnboardingBotChallengeError) {\n control.setError(\n \"Bot protection check failed. Please refresh the page and try again.\",\n );\n options.onError?.(err);\n } else if (err instanceof OnboardingRateLimitError) {\n control.setError(\n err.retryAfterSeconds !== null\n ? `Too many requests. Please wait ${err.retryAfterSeconds}s.`\n : \"Too many requests. Please wait a moment.\",\n );\n options.onError?.(err);\n } else {\n control.setError(\"Something went wrong. Please try again in a moment.\");\n options.onError?.(err);\n }\n }\n }\n\n function onStateChange(\n control: SignupStepperControl,\n state: SignupStepperState,\n ): void {\n // Full step re-render only when the step (or staleness) changed —\n // in-place updates otherwise so typing never loses focus. A consent_stale\n // swap ALSO forces a re-render so the cards re-render cleared + tagged.\n if (\n state.stepIndex !== renderedStepIndex ||\n state.specStale !== renderedStale ||\n state.consentStale !== renderedConsentStale\n ) {\n renderedStepIndex = state.stepIndex;\n renderedStale = state.specStale;\n renderedConsentStale = state.consentStale;\n renderStep(control, state);\n renderStepsIndicator(state);\n }\n\n staleBanner.style.display =\n state.specStale || state.consentStale ? \"\" : \"none\";\n staleBanner.textContent = state.specStale\n ? `This form was just updated by the provider${staleDiffSummary}. Please review your answers below and submit again.`\n : state.consentStale\n ? \"One or more legal documents were updated. Please review and re-accept the updated documents below, then submit again.\"\n : \"\";\n\n setFieldErrorsInPlace(\n stepArea,\n state.errors,\n (path) => `nodii-f-${path.split(\".\")[0] ?? path}`,\n );\n // Account errors overlay (only present on the last step's DOM)\n for (const err of state.accountErrors) {\n const id = accountIdOf(err.path.split(\".\")[0] ?? err.path);\n const errorNode = stepArea.querySelector(idSelector(`${id}-error`));\n if (errorNode) errorNode.textContent = err.message;\n const inputNode = stepArea.querySelector(idSelector(id));\n if (inputNode) inputNode.classList.add(\"has-error\");\n }\n\n // Consent cards' disabled/checked/error state in place (only present on\n // the last step's DOM; a no-op elsewhere or with an empty consentPack).\n // MUST run AFTER setFieldErrorsInPlace — that function blanket-clears every\n // `.nodii-onboarding-field-error` node in stepArea (the consent error nodes\n // carry that class too), so writing consent errors first would be wiped.\n const consentStage = stepArea.querySelector(\n \".nodii-onboarding-consent-stage\",\n ) as HTMLElement | null;\n if (consentStage) {\n updateConsentStep(consentStage, state.consentState, state.consentErrors);\n }\n\n if (state.serverError) {\n serverErrorEl.textContent = state.serverError;\n serverErrorEl.style.display = \"\";\n } else {\n serverErrorEl.style.display = \"none\";\n }\n\n const forwardBtn = stepArea.querySelector(\n \"#nodii-signup-forward\",\n ) as HTMLButtonElement | null;\n if (forwardBtn) {\n forwardBtn.disabled = state.status === \"submitting\";\n }\n\n if (state.status === \"success\") {\n const message =\n state.terminalStage === \"active\"\n ? \"Your account is ready — you're all set!\"\n : state.terminalStage === \"inactive\"\n ? \"Your account was created. Complete verification to activate it.\"\n : \"Thanks for signing up! Check your email to verify your account.\";\n successEl.textContent = message;\n successEl.style.display = \"\";\n form.style.display = \"none\";\n } else {\n // Any non-success status (editing/submitting/error) shows the form and\n // hides the success panel. Without this, a reset()→\"editing\" re-emit\n // would leave the success panel up and the form hidden until reload.\n successEl.style.display = \"none\";\n form.style.display = \"\";\n }\n }\n\n // ── Boot: fetch spec, then build the interactive form ──\n void (async () => {\n let spec: OnboardingSpec;\n try {\n spec = await fetchOnboardingSpec({\n baseUrl: options.baseUrl,\n onboarder: options.onboarder,\n fetch: options.fetch,\n timeoutMs: options.timeoutMs,\n cache,\n // Reuse a spec already loaded for this onboarder this session (a\n // remount into the same page shouldn't re-hit the network). A 409 on\n // submit is the authoritative staleness signal that triggers refetch.\n preferCached: true,\n });\n } catch (err) {\n if (unmounted) return;\n loadingEl.textContent =\n \"The signup form could not be loaded. Please refresh the page.\";\n options.onError?.(err);\n return;\n }\n if (unmounted) return;\n\n siteKey = options.siteKey ?? spec.botChallenge?.siteKey ?? \"\";\n currentSpecVersion = spec.specVersion;\n\n const control = createSignupStepper(spec);\n stepper = control;\n\n form.addEventListener(\"submit\", (event: Event) => {\n event.preventDefault();\n void handleSubmit(control);\n });\n\n form.appendChild(stepsIndicator);\n form.appendChild(staleBanner);\n form.appendChild(stepArea);\n form.appendChild(serverErrorEl);\n\n wrapper.removeChild(loadingEl);\n wrapper.appendChild(successEl);\n wrapper.appendChild(form);\n\n unsubscribe = control.subscribe((state) => onStateChange(control, state));\n // Initial render\n onStateChange(control, control.getState());\n options.onReady?.(spec);\n })();\n\n return {\n unmount() {\n unmounted = true;\n unsubscribe?.();\n if (wrapper.parentNode === host) host.removeChild(wrapper);\n },\n reset() {\n idempotencyKey = null;\n lastFingerprint = null;\n // Force a full re-render on the next state emit so cleared answers\n // actually re-render as empty inputs.\n renderedStepIndex = -1;\n renderedStale = false;\n if (stepper) {\n // stepper.reset() clears answers/credentials/consent and transitions\n // status back to \"editing\"; the emitted state re-renders the form,\n // hides the success panel (via onStateChange's else branch), and\n // repositions to step 0.\n stepper.reset();\n } else {\n form.style.display = \"\";\n successEl.style.display = \"none\";\n }\n },\n };\n}\n","/// <reference lib=\"dom\" />\n/// <reference lib=\"dom.iterable\" />\nexport {\n mountContactForm,\n type ContactFormMountOptions,\n type MountedWidget,\n} from \"./contact-form.js\";\n\nexport { mountSignupForm, type SignupFormMountOptions } from \"./signup-form.js\";\n\nexport { injectWidgetStyles, DEFAULT_WIDGET_CSS } from \"./styles.js\";\n\nexport { cssEscape, idSelector } from \"./dom-utils.js\";\n\n// D543 default ConsentPack step components (opt-in — the headless controller\n// in @nodii/onboarding/consent is enough to build a bespoke consent UI). NO\n// iframe: doc content renders inline same-origin so scroll-to-end is real.\nexport {\n renderConsentStep,\n updateConsentStep,\n consentDocElementId,\n type ConsentStepRenderOptions,\n} from \"./consent-step.js\";\n\n/**\n * Namespace entrypoint mirroring the plan's mount API:\n * OnboardingWidget.mount(el, { onboarder, form: 'contact'|'signup', baseUrl, ... })\n */\nimport { mountContactForm } from \"./contact-form.js\";\nimport type { ContactFormMountOptions, MountedWidget } from \"./contact-form.js\";\nimport { mountSignupForm } from \"./signup-form.js\";\nimport type { SignupFormMountOptions } from \"./signup-form.js\";\n\nexport type WidgetMountOptions =\n ContactFormMountOptions | SignupFormMountOptions;\n\nexport const OnboardingWidget = {\n /**\n * Mount the onboarding widget into a host element.\n *\n * @param el - The DOM element to render into.\n * @param options - Widget configuration. `form: \"contact\"` renders the\n * fixed contact form (Phase 1); `form: \"signup\"` fetches the D540 spec\n * and renders the dynamic stepper (Phase 2 — siteKey comes from the\n * spec's botChallenge unless overridden).\n * @returns A mounted widget control (unmount / reset).\n *\n * @example\n * ```ts\n * import { OnboardingWidget } from \"@nodii/onboarding/widget\";\n *\n * OnboardingWidget.mount(document.getElementById(\"signup-form\")!, {\n * onboarder: \"acme-corp\",\n * form: \"signup\",\n * baseUrl: \"https://api.acme.nucleus-cloud.in\",\n * onSuccess: (r) => console.log(\"landed at\", r.terminalStage),\n * });\n * ```\n */\n mount(el: HTMLElement, options: WidgetMountOptions): MountedWidget {\n if (options.form === \"contact\") {\n return mountContactForm(el, options);\n }\n if (options.form === \"signup\") {\n return mountSignupForm(el, options);\n }\n throw new Error(\n `OnboardingWidget.mount: unknown form \"${(options as { form: string }).form}\". Supported: \"contact\", \"signup\".`,\n );\n },\n} as const;\n"]}
@@ -1 +0,0 @@
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"]}
@@ -1 +0,0 @@
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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/form/schema.ts"],"names":[],"mappings":";;;AAyBO,IAAM,iBAAA,GAAoB,EAAE,MAAA,CAAO;AAAA,EACxC,MAAM,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,GAAG,EAAE,QAAA,EAAS;AAAA,EACnC,WAAA,EAAa,CAAA,CACV,MAAA,EAAO,CACP,GAAA,CAAI,GAAG,0BAA0B,CAAA,CACjC,GAAA,CAAI,GAAA,EAAK,8CAA8C,CAAA;AAAA,EAC1D,WAAA,EAAa,CAAA,CACV,MAAA,EAAO,CACP,GAAA,CAAI,GAAG,0BAA0B,CAAA,CACjC,GAAA,CAAI,GAAA,EAAK,8CAA8C,CAAA;AAAA,EAC1D,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,MAAM,mCAAmC,CAAA;AAAA,EAC3D,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC3B,OAAA,EAAS,EACN,MAAA,EAAO,CACP,IAAI,GAAA,EAAM,0CAA0C,EACpD,QAAA,EAAS;AAAA,EACZ,eAAA,EAAiB,CAAA,CAAE,KAAA,CAAM,CAAA,CAAE,QAAO,CAAE,GAAA,CAAI,CAAC,CAAC,EAAE,GAAA,CAAI,EAAE,CAAA,CAAE,OAAA,CAAQ,EAAE,CAAA;AAAA,EAC9D,UAAU,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,EAAE,EAAE,QAAA,EAAS;AAAA,EACtC,WAAA,EAAa,EACV,MAAA,CAAO;AAAA,IACN,cAAc,CAAA,CAAE,MAAA,CAAO,EAAE,MAAA,EAAQ,EAAE,QAAA,EAAS;AAAA,IAC5C,eAAe,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,IAAI,EAAE,QAAA,EAAS;AAAA,IAC7C,aAAa,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,IAAI,EAAE,QAAA,EAAS;AAAA,IAC3C,QAAQ,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,GAAG,EAAE,QAAA;AAAS,GACtC,CAAA,CACA,MAAA,EAAO,CACP,QAAA,EAAS;AAAA,EACZ,yBAAA,EAA2B,EACxB,OAAA,EAAQ,CACR,OAAO,CAAC,KAAA,KAAU,OAAO,4CAA4C,CAAA;AAAA,EACxE,cAAA,EAAgB,EAAE,OAAA,EAAQ;AAAA,EAC1B,YAAY,CAAA,CAAE,IAAA,CAAK,CAAC,SAAA,EAAW,SAAS,CAAC,CAAA;AAAA;AAAA,EAEzC,SAAS,CAAA,CAAE,MAAA,GAAS,GAAA,CAAI,CAAC,EAAE,QAAA;AAC7B,CAAC;AAYM,IAAM,eAAA,GAAkB,kBAC5B,MAAA,CAAO;AAAA,EACN,QAAA,EAAU,EAAE,MAAA,EAAO,CAAE,IAAI,CAAA,EAAG,sBAAsB,EAAE,QAAA;AACtD,CAAC,EACA,MAAA;AAQI,SAAS,oBAAoB,MAAA,EAAiB;AACnD,EAAA,OAAO,iBAAA,CAAkB,UAAU,MAAM,CAAA;AAC3C;AAQO,SAAS,qBAAqB,OAAA,EAAkB;AACrD,EAAA,OAAO,eAAA,CAAgB,UAAU,OAAO,CAAA;AAC1C","file":"chunk-SIMLMQPT.js","sourcesContent":["/**\n * Contact-form Zod schema — mirrors the LOCKED hub REST contract exactly:\n * POST /api/v1/public/onboarding/leads\n * Schema: PublicOnboardingLeadsRequest (hub id 8686dd33)\n *\n * Constraints (per hub JSON Schema):\n * name — string, 1-200 chars, required\n * email — email format, required\n * phone — string, optional (no server-side constraint beyond string)\n * message — string, ≤4000 chars, optional\n * botToken — string, required (reCAPTCHA token, D537)\n *\n * additionalProperties: false\n *\n * The schema intentionally does NOT include botToken in the public-facing\n * ContactFormValues type — that field is injected by the submit client right\n * before the POST (the widget/form never exposes it to the user).\n */\n\nimport { z } from \"zod/v3\";\n\n/**\n * The user-visible contact form fields. Validated client-side for UX.\n * Server re-validates authoritatively (D540 §2).\n */\nexport const contactFormSchema = z.object({\n name: z.string().max(200).optional(),\n companyName: z\n .string()\n .min(1, \"Company name is required\")\n .max(200, \"Company name must be 200 characters or fewer\"),\n contactName: z\n .string()\n .min(1, \"Contact name is required\")\n .max(200, \"Contact name must be 200 characters or fewer\"),\n email: z.string().email(\"A valid email address is required\"),\n phone: z.string().optional(),\n message: z\n .string()\n .max(4000, \"Message must be 4000 characters or fewer\")\n .optional(),\n interestModules: z.array(z.string().min(1)).max(32).default([]),\n sizeBand: z.string().max(80).optional(),\n attribution: z\n .object({\n campaignTags: z.record(z.string()).optional(),\n referringSite: z.string().max(2048).optional(),\n landingPage: z.string().max(2048).optional(),\n button: z.string().max(120).optional(),\n })\n .strict()\n .optional(),\n privacyNoticeAcknowledged: z\n .boolean()\n .refine((value) => value, \"Privacy notice acknowledgement is required\"),\n marketingOptIn: z.boolean(),\n intakeKind: z.enum([\"contact\", \"enquiry\"]),\n // Q46 default: a visually-hidden field. Humans leave it empty.\n website: z.string().max(0).optional(),\n});\n\nexport type ContactFormValues = z.infer<typeof contactFormSchema>;\n\n/**\n * The full wire payload — contactFormSchema + botToken.\n *\n * STRICT mode: unknown keys are REJECTED (not stripped), mirroring the\n * server's `additionalProperties: false`. `submitLead` runs every outgoing\n * payload through this schema before the POST — an extra key never reaches\n * the wire; it fails fast client-side with OnboardingValidationError.\n */\nexport const leadsWireSchema = contactFormSchema\n .extend({\n botToken: z.string().min(1, \"botToken is required\").optional(),\n })\n .strict();\n\nexport type LeadsWirePayload = z.infer<typeof leadsWireSchema>;\n\n/**\n * Validate user-visible form values (no botToken required here).\n * Returns a Zod SafeParseReturnType (inferred).\n */\nexport function validateContactForm(values: unknown) {\n return contactFormSchema.safeParse(values);\n}\n\n/**\n * Validate the full wire payload (including botToken) before submission.\n * STRICT: unknown keys are rejected, matching additionalProperties:false.\n * This is the exact validation `submitLead` applies on the wire path.\n * Returns a Zod SafeParseReturnType (inferred).\n */\nexport function validateLeadsPayload(payload: unknown) {\n return leadsWireSchema.safeParse(payload);\n}\n"]}