@broadpaper/pdf 0.1.1 → 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.
@@ -52,7 +52,8 @@ var LicenseFormatError = class extends Error {
52
52
  }
53
53
  kind;
54
54
  };
55
- var ENTITLEMENTS = ["internal", "saas"];
55
+ var PLANS = ["internal", "saas"];
56
+ var LICENSE_TYPES = ["subscription"];
56
57
  function normalizeLicense(license) {
57
58
  return license.replace(/\s+/g, "");
58
59
  }
@@ -96,11 +97,11 @@ function parseLicense(license) {
96
97
  function readPayload(raw) {
97
98
  if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new LicenseFormatError("the licence payload is not an object");
98
99
  const o = raw;
99
- const version = o.version;
100
- if (version !== 1) {
101
- const numeric = typeof version === "number" && Number.isInteger(version) && version > 1;
100
+ const schemaVersion = o.schemaVersion;
101
+ if (schemaVersion !== 1) {
102
+ const numeric = typeof schemaVersion === "number" && Number.isInteger(schemaVersion) && schemaVersion > 1;
102
103
  throw new LicenseFormatError(
103
- numeric ? `licence payload version ${version} is newer than this version of BroadPaper, which reads version 1` : "the licence payload has no usable version",
104
+ numeric ? `licence payload schema version ${schemaVersion} is newer than this version of BroadPaper, which reads version 1` : "the licence payload has no usable schemaVersion",
104
105
  numeric ? "unsupported" : "invalid"
105
106
  );
106
107
  }
@@ -114,21 +115,32 @@ function readPayload(raw) {
114
115
  if (typeof value !== "number" || !Number.isFinite(value)) throw new LicenseFormatError(`the licence payload is missing ${key}`);
115
116
  return value;
116
117
  };
117
- const entitlement = text("entitlement");
118
- if (!ENTITLEMENTS.includes(entitlement)) {
119
- throw new LicenseFormatError(`this version of BroadPaper does not know the entitlement ${JSON.stringify(entitlement)}`, "unsupported");
118
+ const secondsOrNever = (key) => {
119
+ const value = o[key];
120
+ if (value === null) return null;
121
+ return seconds(key);
122
+ };
123
+ const plan = text("plan");
124
+ if (!PLANS.includes(plan)) {
125
+ throw new LicenseFormatError(`this version of BroadPaper does not know the plan ${JSON.stringify(plan)}`, "unsupported");
126
+ }
127
+ const licenseType = text("licenseType");
128
+ if (!LICENSE_TYPES.includes(licenseType)) {
129
+ throw new LicenseFormatError(`this version of BroadPaper cannot honour a ${JSON.stringify(licenseType)} licence`, "unsupported");
120
130
  }
121
131
  return {
122
132
  ...o,
123
- version: 1,
133
+ schemaVersion: 1,
124
134
  keyId: text("keyId"),
125
135
  licenseId: text("licenseId"),
126
- customerId: text("customerId"),
127
- customerName: text("customerName"),
136
+ organisationId: text("organisationId"),
137
+ organisationName: text("organisationName"),
128
138
  product: text("product"),
129
- entitlement,
139
+ plan,
140
+ licenseType,
130
141
  issuedAt: seconds("issuedAt"),
131
- expiresAt: seconds("expiresAt")
142
+ validUntil: secondsOrNever("validUntil"),
143
+ updatesUntil: seconds("updatesUntil")
132
144
  };
133
145
  }
134
146
 
@@ -596,8 +608,8 @@ function unlicensed() {
596
608
  state: "unlicensed",
597
609
  licensed: false,
598
610
  payload: null,
599
- entitlement: null,
600
- expiresAt: null,
611
+ plan: null,
612
+ validUntil: null,
601
613
  daysRemaining: null,
602
614
  message: "No BroadPaper licence is configured, so PDFs carry the evaluation watermark. Everything else works; see https://www.broadpaper.com/docs/guide/licensing."
603
615
  };
@@ -607,8 +619,8 @@ function failure(state, message, payload = null) {
607
619
  state,
608
620
  licensed: false,
609
621
  payload,
610
- entitlement: null,
611
- expiresAt: payload ? new Date(payload.expiresAt * 1e3) : null,
622
+ plan: null,
623
+ validUntil: payload?.validUntil != null ? new Date(payload.validUntil * 1e3) : null,
612
624
  daysRemaining: null,
613
625
  message
614
626
  };
@@ -653,17 +665,20 @@ async function verifyLicense(license, options = {}) {
653
665
  return failure("invalid", "This BroadPaper licence failed its signature check \u2014 it has been altered or truncated. PDFs carry the evaluation watermark.", payload);
654
666
  }
655
667
  const now = options.now ?? /* @__PURE__ */ new Date();
656
- const expiresAt = new Date(payload.expiresAt * 1e3);
668
+ if (payload.validUntil === null) {
669
+ return { state: "active", licensed: true, payload, plan: payload.plan, validUntil: null, daysRemaining: null, message: null };
670
+ }
671
+ const validUntil = new Date(payload.validUntil * 1e3);
657
672
  const graceDays = options.gracePeriodDays ?? DEFAULT_GRACE_PERIOD_DAYS;
658
- const msRemaining = expiresAt.getTime() - now.getTime();
673
+ const msRemaining = validUntil.getTime() - now.getTime();
659
674
  const daysRemaining = Math.floor(msRemaining / DAY_MS);
660
675
  if (msRemaining > 0) {
661
676
  return {
662
677
  state: "active",
663
678
  licensed: true,
664
679
  payload,
665
- entitlement: payload.entitlement,
666
- expiresAt,
680
+ plan: payload.plan,
681
+ validUntil,
667
682
  daysRemaining,
668
683
  message: null
669
684
  };
@@ -674,15 +689,15 @@ async function verifyLicense(license, options = {}) {
674
689
  state: "grace",
675
690
  licensed: true,
676
691
  payload,
677
- entitlement: payload.entitlement,
678
- expiresAt,
692
+ plan: payload.plan,
693
+ validUntil,
679
694
  daysRemaining,
680
- message: `The BroadPaper licence for ${payload.customerName} expired ${daysOver} day${daysOver === 1 ? "" : "s"} ago and is inside its ${graceDays}-day grace period. Renew it and copy the new licence from your account, or PDFs will start carrying the evaluation watermark.`
695
+ message: `The BroadPaper licence for ${payload.organisationName} expired ${daysOver} day${daysOver === 1 ? "" : "s"} ago and is inside its ${graceDays}-day grace period. Renew it and copy the new licence from your account, or PDFs will start carrying the evaluation watermark.`
681
696
  };
682
697
  }
683
698
  return failure(
684
699
  "expired",
685
- `The BroadPaper licence for ${payload.customerName} expired on ${expiresAt.toISOString().slice(0, 10)} and its ${graceDays}-day grace period has passed, so PDFs carry the evaluation watermark. Renewing issues a new licence in your BroadPaper account.`,
700
+ `The BroadPaper licence for ${payload.organisationName} expired on ${validUntil.toISOString().slice(0, 10)} and its ${graceDays}-day grace period has passed, so PDFs carry the evaluation watermark. Renewing issues a new licence in your BroadPaper account.`,
686
701
  payload
687
702
  );
688
703
  }
@@ -1157,4 +1172,4 @@ export {
1157
1172
  @noble/ed25519/index.js:
1158
1173
  (*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) *)
1159
1174
  */
1160
- //# sourceMappingURL=chunk-4YSTS7DA.js.map
1175
+ //# sourceMappingURL=chunk-PFCVDSUU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../license/src/encoding.ts","../../license/src/format.ts","../../../node_modules/.pnpm/@noble+ed25519@3.2.0/node_modules/@noble/ed25519/index.js","../../license/src/trusted-keys.ts","../../license/src/types.ts","../../license/src/verify.ts","../../license/src/config.ts","../../license/src/watermark.ts","../src/server/ssrf.ts","../src/server/render-pdf.ts","../src/server/watermark.ts","../src/server/http.ts"],"sourcesContent":["/**\n * base64url and UTF-8, without depending on Node or on the DOM.\n *\n * The SDK runs in Node, in edge runtimes, in a worker and in a browser, and the\n * licence string has to decode identically in all four. `atob`/`btoa` exist\n * everywhere modern but are byte-oriented and mangle anything above U+00FF, so\n * text goes through `TextEncoder`/`TextDecoder` first and only bytes are\n * base64'd. The tables below are the whole implementation, which is smaller\n * than the runtime detection needed to use `Buffer` where it happens to exist.\n */\n\nconst ALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\nconst LOOKUP = /* @__PURE__ */ (() => {\n const t = new Int8Array(128).fill(-1);\n for (let i = 0; i < ALPHABET.length; i++) t[ALPHABET.charCodeAt(i)] = i;\n // Accept standard base64 as well, so a licence that survived a round trip\n // through a system that rewrote the alphabet still reads.\n t[\"+\".charCodeAt(0)] = 62;\n t[\"/\".charCodeAt(0)] = 63;\n return t;\n})();\n\nexport function bytesToBase64Url(bytes: Uint8Array): string {\n let out = \"\";\n let i = 0;\n for (; i + 2 < bytes.length; i += 3) {\n const n = (bytes[i]! << 16) | (bytes[i + 1]! << 8) | bytes[i + 2]!;\n out += ALPHABET[(n >>> 18) & 63]! + ALPHABET[(n >>> 12) & 63]! + ALPHABET[(n >>> 6) & 63]! + ALPHABET[n & 63]!;\n }\n const rest = bytes.length - i;\n if (rest === 1) {\n const n = bytes[i]! << 16;\n out += ALPHABET[(n >>> 18) & 63]! + ALPHABET[(n >>> 12) & 63]!;\n } else if (rest === 2) {\n const n = (bytes[i]! << 16) | (bytes[i + 1]! << 8);\n out += ALPHABET[(n >>> 18) & 63]! + ALPHABET[(n >>> 12) & 63]! + ALPHABET[(n >>> 6) & 63]!;\n }\n return out;\n}\n\n/** Throws on anything that is not base64/base64url. Padding is optional. */\nexport function base64UrlToBytes(text: string): Uint8Array {\n let end = text.length;\n while (end > 0 && text[end - 1] === \"=\") end--;\n const chars: number[] = [];\n for (let i = 0; i < end; i++) {\n const code = text.charCodeAt(i);\n const value = code < 128 ? LOOKUP[code]! : -1;\n if (value < 0) throw new Error(`not base64: ${JSON.stringify(text[i])} at ${i}`);\n chars.push(value);\n }\n // 4 base64 characters carry 3 bytes; a group of 1 is never valid.\n if (chars.length % 4 === 1) throw new Error(\"not base64: truncated\");\n const out = new Uint8Array(Math.floor((chars.length * 3) / 4));\n let o = 0;\n let i = 0;\n for (; i + 3 < chars.length; i += 4) {\n const n = (chars[i]! << 18) | (chars[i + 1]! << 12) | (chars[i + 2]! << 6) | chars[i + 3]!;\n out[o++] = (n >>> 16) & 255;\n out[o++] = (n >>> 8) & 255;\n out[o++] = n & 255;\n }\n const rest = chars.length - i;\n if (rest === 2) {\n out[o++] = ((chars[i]! << 18) | (chars[i + 1]! << 12)) >>> 16;\n } else if (rest === 3) {\n const n = (chars[i]! << 18) | (chars[i + 1]! << 12) | (chars[i + 2]! << 6);\n out[o++] = (n >>> 16) & 255;\n out[o++] = (n >>> 8) & 255;\n }\n return out;\n}\n\nconst encoder = /* @__PURE__ */ new TextEncoder();\nconst decoder = /* @__PURE__ */ new TextDecoder(\"utf-8\", { fatal: true });\n\nexport const utf8ToBytes = (text: string): Uint8Array => encoder.encode(text);\nexport const bytesToUtf8 = (bytes: Uint8Array): string => decoder.decode(bytes);\n","/**\n * The licence string.\n *\n * BP1.<base64url payload>.<base64url signature>\n *\n * Three parts, dot-separated, safe in an environment variable, a YAML file, a\n * URL and a shell argument without quoting. The leading `BP1` is the *string\n * format* version and `payload.version` is the *payload schema* version; they\n * move independently, and both are checked, so a licence issued for a later\n * format is reported as unsupported rather than as corrupt.\n *\n * What is signed is the bytes of `BP1.<payload>` — prefix included. Signing the\n * encoded text rather than the decoded object means verification never depends\n * on two JSON serialisers agreeing about key order or number formatting, and\n * covering the prefix stops a payload being lifted into a future format that\n * might read a field differently.\n */\nimport { base64UrlToBytes, bytesToBase64Url, bytesToUtf8, utf8ToBytes } from \"./encoding.js\";\nimport { PRODUCT, type LicensePayload, type LicenseType, type Plan } from \"./types.js\";\n\n/** The only string format this SDK can read. */\nexport const FORMAT_PREFIX = \"BP1\";\n\n/** A licence string split into its parts, before any signature check. */\nexport interface ParsedLicense {\n prefix: string;\n /** The exact text that was signed. */\n signedText: string;\n encodedPayload: string;\n signature: Uint8Array;\n payload: LicensePayload;\n}\n\nexport class LicenseFormatError extends Error {\n constructor(\n message: string,\n /** `unsupported` when the licence is well-formed but newer than this SDK. */\n readonly kind: \"invalid\" | \"unsupported\" = \"invalid\"\n ) {\n super(message);\n this.name = \"LicenseFormatError\";\n }\n}\n\nconst PLANS: readonly Plan[] = [\"internal\", \"saas\"];\n\n/**\n * The licence types this SDK can actually honour.\n *\n * Only `subscription`. A perpetual licence's whole meaning is that the right to\n * use outlives the right to updates, which needs the running build's release\n * date to enforce — a fact a certificate cannot carry, because it is issued\n * before the versions it covers exist. A build with no such date could only\n * honour a perpetual licence by honouring *every* future version forever, which\n * is not what was sold. So it is refused, and refused as `unsupported` rather\n * than `invalid`: the fix is to upgrade, and saying so is more use than calling\n * a valid certificate corrupt.\n */\nconst LICENSE_TYPES: readonly LicenseType[] = [\"subscription\"];\n\n/** Whitespace is stripped: licences get pasted, wrapped and indented. */\nexport function normalizeLicense(license: string): string {\n return license.replace(/\\s+/g, \"\");\n}\n\n/**\n * Reads a licence string without verifying it.\n *\n * Nothing here decides whether a licence is *honoured* — that needs the\n * signature — but a structurally broken string can be rejected before any\n * cryptography happens, and the account UI can display a licence's contents\n * without holding a public key.\n */\nexport function parseLicense(license: string): ParsedLicense {\n const text = normalizeLicense(license);\n if (!text) throw new LicenseFormatError(\"the licence string is empty\");\n\n const parts = text.split(\".\");\n if (parts.length !== 3) throw new LicenseFormatError(`expected three dot-separated parts, found ${parts.length}`);\n const [prefix, encodedPayload, encodedSignature] = parts as [string, string, string];\n\n if (prefix !== FORMAT_PREFIX) {\n // A licence issued in a format this SDK predates is a version problem, not\n // a corrupt string, and the fix is to upgrade rather than to re-copy it.\n const known = /^BP\\d+$/.test(prefix);\n throw new LicenseFormatError(\n known\n ? `licence format ${prefix} is newer than this version of BroadPaper, which reads ${FORMAT_PREFIX}`\n : `unrecognised licence prefix ${JSON.stringify(prefix)}`,\n known ? \"unsupported\" : \"invalid\"\n );\n }\n if (!encodedPayload || !encodedSignature) throw new LicenseFormatError(\"the licence string has an empty part\");\n\n let json: string;\n let signature: Uint8Array;\n try {\n json = bytesToUtf8(base64UrlToBytes(encodedPayload));\n signature = base64UrlToBytes(encodedSignature);\n } catch (e) {\n throw new LicenseFormatError(`the licence string is not valid base64 (${(e as Error).message})`);\n }\n if (signature.length !== 64) throw new LicenseFormatError(`an Ed25519 signature is 64 bytes, this one is ${signature.length}`);\n\n let raw: unknown;\n try {\n raw = JSON.parse(json);\n } catch {\n throw new LicenseFormatError(\"the licence payload is not valid JSON\");\n }\n\n return {\n prefix,\n signedText: `${prefix}.${encodedPayload}`,\n encodedPayload,\n signature,\n payload: readPayload(raw)\n };\n}\n\n/**\n * Validates the payload's shape.\n *\n * Unknown properties are kept, not rejected: they are inside the signature, so\n * a licence issued by a later BroadPaper carrying a field this SDK has never\n * heard of is still a licence this SDK can honour.\n */\nfunction readPayload(raw: unknown): LicensePayload {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) throw new LicenseFormatError(\"the licence payload is not an object\");\n const o = raw as Record<string, unknown>;\n\n const schemaVersion = o.schemaVersion;\n if (schemaVersion !== 1) {\n const numeric = typeof schemaVersion === \"number\" && Number.isInteger(schemaVersion) && schemaVersion > 1;\n throw new LicenseFormatError(\n numeric\n ? `licence payload schema version ${schemaVersion} is newer than this version of BroadPaper, which reads version 1`\n : \"the licence payload has no usable schemaVersion\",\n numeric ? \"unsupported\" : \"invalid\"\n );\n }\n\n const text = (key: string): string => {\n const value = o[key];\n if (typeof value !== \"string\" || value === \"\") throw new LicenseFormatError(`the licence payload is missing ${key}`);\n return value;\n };\n const seconds = (key: string): number => {\n const value = o[key];\n if (typeof value !== \"number\" || !Number.isFinite(value)) throw new LicenseFormatError(`the licence payload is missing ${key}`);\n return value;\n };\n // `null` is the honest encoding of \"no end date\" — a sentinel year 9999 would\n // be a date somebody eventually compares against. Absent is still an error;\n // only an explicit null means never.\n const secondsOrNever = (key: string): number | null => {\n const value = o[key];\n if (value === null) return null;\n return seconds(key);\n };\n\n const plan = text(\"plan\");\n if (!PLANS.includes(plan as Plan)) {\n // A plan this SDK does not know is a newer commercial model, and refusing\n // to honour a licence we cannot classify would punish the customer for\n // buying something new. It is reported as unsupported so the developer is\n // told to upgrade.\n throw new LicenseFormatError(`this version of BroadPaper does not know the plan ${JSON.stringify(plan)}`, \"unsupported\");\n }\n\n const licenseType = text(\"licenseType\");\n if (!LICENSE_TYPES.includes(licenseType as LicenseType)) {\n throw new LicenseFormatError(`this version of BroadPaper cannot honour a ${JSON.stringify(licenseType)} licence`, \"unsupported\");\n }\n\n return {\n ...o,\n schemaVersion: 1,\n keyId: text(\"keyId\"),\n licenseId: text(\"licenseId\"),\n organisationId: text(\"organisationId\"),\n organisationName: text(\"organisationName\"),\n product: text(\"product\") as typeof PRODUCT,\n plan: plan as Plan,\n licenseType: licenseType as LicenseType,\n issuedAt: seconds(\"issuedAt\"),\n validUntil: secondsOrNever(\"validUntil\"),\n updatesUntil: seconds(\"updatesUntil\")\n };\n}\n\n/**\n * Encodes a payload into the text that gets signed.\n *\n * Exported because BroadPaper's own licence issuer must produce byte-identical\n * input to what the SDK verifies, and the only way to guarantee that is for\n * both to call this function.\n */\nexport function encodeSigningInput(payload: LicensePayload): { signedText: string; encodedPayload: string } {\n const encodedPayload = bytesToBase64Url(utf8ToBytes(JSON.stringify(payload)));\n return { encodedPayload, signedText: `${FORMAT_PREFIX}.${encodedPayload}` };\n}\n\n/** Assembles the final licence string from a payload and its signature. */\nexport function formatLicense(payload: LicensePayload, signature: Uint8Array): string {\n if (signature.length !== 64) throw new LicenseFormatError(`an Ed25519 signature is 64 bytes, this one is ${signature.length}`);\n const { encodedPayload } = encodeSigningInput(payload);\n return `${FORMAT_PREFIX}.${encodedPayload}.${bytesToBase64Url(signature)}`;\n}\n","/*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) */\n/**\n * 5KB JS implementation of ed25519 EdDSA signatures.\n * Targets RFC8032, FIPS 186-5, and ZIP215 behavior.\n * @module\n * @example\n * ```js\nimport * as ed from '@noble/ed25519';\n(async () => {\n const secretKey = ed.utils.randomSecretKey();\n const message = Uint8Array.from([0xab, 0xbc, 0xcd, 0xde]);\n const pubKey = await ed.getPublicKeyAsync(secretKey); // Sync methods are also present\n const signature = await ed.signAsync(message, secretKey);\n const isValid = await ed.verifyAsync(signature, message, pubKey);\n})();\n```\n */\n/**\n * Curve params. edwards25519 uses the RFC equation `-x² + y² = 1 + dx²y²`.\n * The stored `a` literal below is `p - 1`, i.e. the field-element encoding of RFC `a = -1`.\n * * P = `2n**255n - 19n` // field over which calculations are done\n * * N = `2n**252n + 27742317777372353535851937790883648493n` // prime-order subgroup order\n * * h = 8 // cofactor\n * * a = `Fp.create(BigInt(-1))` // equation param, stored here as `p - 1`\n * * d = -121665/121666 a.k.a. `Fp.neg(121665 * Fp.inv(121666))` // equation param\n * * Gx, Gy are coordinates of Generator / base point\n *\n * Mirror noble-curves: Point.CURVE() exposes shared params, but callers must not be able to mutate\n * that shared view and desynchronize it from the arithmetic constants captured below.\n */\nconst freeze = Object.freeze;\nconst P = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn;\nconst N = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn;\nconst _d = 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n;\nconst Gx = 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an;\nconst Gy = 0x6666666666666666666666666666666666666666666666666666666666666658n;\nconst _a = P - 1n; // field-element encoding of RFC `a = -1`\nconst ed25519_CURVE = freeze({\n p: P,\n n: N,\n h: 8n,\n a: _a,\n d: _d,\n Gx,\n Gy,\n});\n// Shared 32-byte encoded width for Ed25519 points, scalars, signatures/2, and keys. Named LEN\n// rather than RFC 8032's `L`, which names the group order (stored here as `N`).\nconst LEN = 32;\n// Helpers and Precomputes sections are reused between libraries\n// ## Helpers\n// ----------\n/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */\nconst isBytes = (a) => {\n // Plain `instanceof Uint8Array` is too strict for some Buffer / proxy / cross-realm cases.\n // The fallback still requires a real ArrayBuffer view, so plain\n // JSON-deserialized `{ constructor: ... }` spoofing is rejected, and\n // `BYTES_PER_ELEMENT === 1` keeps the fallback on byte-oriented views.\n return (a instanceof Uint8Array ||\n (ArrayBuffer.isView(a) &&\n a.constructor.name === 'Uint8Array' &&\n a.BYTES_PER_ELEMENT === 1));\n};\n/** Asserts something is Bytes. */\nconst abytes = (value, length, title = '') => {\n // Success path first: this runs at the start of every update() / digestInto(), and the\n // common `abytes(data)` form must not pay for length handling it does not use.\n if (isBytes(value) && (length === undefined || value.length === length))\n return value;\n // Error path: recompute freely to build the exact message.\n const bytes = isBytes(value);\n const ofLen = length !== undefined ? ` of length ${length}` : '';\n const got = bytes ? `length=${value.length}` : `type=${typeof value}`;\n const message = (title ? `\"${title}\" ` : '') + 'expected Uint8Array' + ofLen + ', got ' + got;\n if (!bytes)\n throw new TypeError(message);\n throw new RangeError(message);\n};\n// Validate, then take one owned copy, so later caller mutation cannot be observed — e.g. cannot\n// make sign()'s nonce derivation and challenge derivation see different messages.\nconst snapshotBytes = (value, title = '', length) => Uint8Array.from(abytes(value, length, title));\n// Callers keep values non-negative and within the requested width; padStart() won't truncate over-wide inputs.\nconst padh = (n, pad) => n.toString(16).padStart(pad, '0');\n/** Convert byte array to hex string. */\nconst bytesToHex = (bytes) => {\n let hex = '';\n for (const byte of abytes(bytes))\n hex += padh(byte, 2);\n return hex;\n};\n/** Convert hex string to byte array. */\nconst hexToBytes = (hex) => {\n const e = 'hex invalid'; // Strict ASCII hex only, with one generic error for parse failures.\n if (typeof hex !== 'string')\n throw new TypeError(e);\n if (hex.length % 2 || !/^[\\da-f]*$/i.test(hex))\n throw new RangeError(e);\n const array = new Uint8Array(hex.length / 2);\n for (let ai = 0, hi = 0; ai < array.length; ai++, hi += 2) {\n const n1 = hex.charCodeAt(hi);\n const n2 = hex.charCodeAt(hi + 1);\n // Regex guarantees ASCII. For 0..9/A..F/a..f, this maps char codes to 0..15.\n array[ai] = ((n1 & 15) + (n1 >> 6) * 9) * 16 + (n2 & 15) + (n2 >> 6) * 9;\n }\n return array;\n};\n// WebCrypto is available in all modern environments\n/** Copies several Uint8Arrays into one. */\nconst concatBytes = (...arrays) => {\n let sum = 0;\n for (const a of arrays)\n sum += abytes(a).length;\n const res = new Uint8Array(sum);\n let pad = 0;\n for (const a of arrays) {\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n};\n/**\n * WebCrypto OS-level CSPRNG (random number generator).\n * Will throw when not available; large-request ceilings are delegated to getRandomValues().\n */\nconst randomBytes = (len = LEN) => {\n const c = globalThis?.crypto;\n if (typeof c?.getRandomValues !== 'function')\n throw new Error('crypto.getRandomValues must be defined, consider polyfill');\n return c.getRandomValues(new Uint8Array(len));\n};\n/** Inclusive-lower, exclusive-upper bigint range assertion. */\nconst arange = (n, min, max, msg = 'bad number: out of range') => {\n if (typeof n !== 'bigint')\n throw new TypeError(msg);\n if (min <= n && n < max)\n return n;\n throw new RangeError(msg);\n};\n/** Canonical modular reduction. Callers must provide a positive modulus. */\nconst mod = (a, b = P) => ((a %= b) >= 0n ? a : b + a);\n// Low-255-bit mask used by the `2^255 - 19` fast reduction in `modP(...)`.\nconst P_MASK = (1n << 255n) - 1n;\n// Fast reduction for the special prime `2^255 - 19`. This path assumes nonnegative inputs; the\n// generic fallback would simply be `mod(num, P)`.\nconst modP = (num) => {\n if (num < 0n)\n throw new RangeError('negative coordinate');\n let r = (num >> 255n) * 19n + (num & P_MASK);\n r = (r >> 255n) * 19n + (r & P_MASK);\n return r % P;\n};\n// Reduce modulo the subgroup order stored in implementation constant `N` (RFC 8032's `L`).\nconst modN = (a) => mod(a, N);\n/** Modular inversion using extended euclidean GCD. Variable-time (non-CT). */\nconst invert = (number, modulo) => {\n if (number === 0n)\n throw new Error('invert: expected non-zero number');\n // modulo = 1 is the zero ring: gcd(x, 1) = 1 makes the loop below \"succeed\" and return the\n // useless inverse 0. Reject it like pow() and invertCt() do.\n if (modulo <= 1n)\n throw new Error('invert: expected modulus > 1, got ' + modulo);\n // This is variable-time: the loop count depends on `number`.\n let a = mod(number, modulo);\n let b = modulo;\n // Only the Bézout coefficient of `number` (x/u chain) is tracked; the coefficient of `modulo`\n // never affects the output, so it is not computed.\n // prettier-ignore\n let x = 0n, u = 1n;\n while (a !== 0n) {\n const q = b / a;\n const r = b - a * q;\n const m = x - u * q;\n // prettier-ignore\n b = a, a = r, x = u, u = m;\n }\n const gcd = b;\n if (gcd !== 1n)\n throw new Error('invert: does not exist');\n return mod(x, modulo);\n};\n// Dynamic lookup keeps sync/async hash providers configurable at runtime. Both exported slots are\n// caller-owned and may be unset; wrapper helpers use this lookup first and then enforce the digest\n// contract instead of trusting provider output.\nconst _hash = (name) => {\n // @ts-ignore\n const fn = hashes[name];\n if (typeof fn !== 'function')\n throw new Error('hashes.' + name + ' not set');\n return fn;\n};\n// All exported provider slots are caller-configurable and may be unset or return arbitrary values,\n// so wrapper helpers must enforce the exact 64-byte SHA-512 digest contract instead of trusting providers.\nconst callHash = (name, ...m) => abytes(_hash(name)(concatBytes(...m)), 64, 'digest');\nconst callHashAsync = async (name, ...m) => abytes(await _hash(name)(concatBytes(...m)), 64, 'digest');\n/**\n * SHA-512 helper used by the synchronous API.\n * @param msg - Message bytes to hash.\n * @returns 64-byte SHA-512 digest.\n * @example\n * Hash message bytes after wiring the synchronous SHA-512 implementation.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const digest = ed.hash(new Uint8Array([1, 2, 3]));\n * ```\n */\n// Public helper validates the message boundary explicitly; the configured provider is still looked\n// up dynamically and its output is checked with `callHash(...)`.\nconst hash = (msg) => callHash('sha512', abytes(msg, undefined, 'message'));\n// Runtime class guard: this is `instanceof Point`, so cross-realm / duplicate-bundle Point objects\n// are rejected even if they are structurally identical.\nconst apoint = (p) => {\n if (p instanceof Point)\n return p;\n throw new TypeError('Point expected');\n};\n// ## End of Helpers\n// -----------------\n// Exclusive upper bound `2^256` used by 32-byte decode/serialization range checks.\nconst B256 = 2n ** 256n;\n/**\n * Point in XYZT extended coordinates.\n * @param X - X coordinate.\n * @param Y - Y coordinate.\n * @param Z - Projective Z coordinate.\n * @param T - Cached cross-product term.\n * @example\n * Do point arithmetic with the built-in base point and encode the result as hex.\n *\n * ```ts\n * const hex = Point.BASE.double().toHex();\n * ```\n */\nclass Point {\n static BASE;\n static ZERO;\n X;\n Y;\n Z;\n T;\n // Constructor only bounds-checks and freezes XYZT coordinates; it does not prove the point is\n // on-curve or that T matches X*Y/Z.\n constructor(X, Y, Z, T) {\n const max = B256;\n this.X = arange(X, 0n, max);\n this.Y = arange(Y, 0n, max);\n this.Z = arange(Z, 1n, max);\n this.T = arange(T, 0n, max);\n freeze(this);\n }\n static CURVE() {\n return ed25519_CURVE;\n }\n static fromAffine(p) {\n return new Point(p.x, p.y, 1n, modP(p.x * p.y));\n }\n /** RFC8032 5.1.3: Uint8Array to Point. */\n static fromBytes(bytes, zip215 = false) {\n const normed = snapshotBytes(bytes, 'point', LEN); // owned copy: sign-bit mask below mutates it\n // adjust first LE byte = last BE byte\n const lastByte = normed[31];\n normed[31] = lastByte & ~0x80;\n const y = bytesToNumberLE(normed);\n // After clearing the sign bit, parsed `y` is always < 2^255. ZIP-215 still accepts the full\n // post-mask range here, while strict RFC8032 decoding further requires `y < p`.\n if (!zip215)\n arange(y, 0n, P);\n const y2 = modP(y * y); // y²\n const u = mod(y2 - 1n); // u=y²-1\n const v = modP(_d * y2 + 1n); // v=dy²+1\n let { isValid, value: x } = uvRatio(u, v); // (uv³)(uv⁷)^(p-5)/8; square root\n if (!isValid)\n throw new Error('bad point: y not sqrt'); // not square root: bad point\n const isLastByteOdd = !!(lastByte & 0x80); // x_0, last bit\n // ZIP-215-compatible decoding keeps the x=0 / sign-bit=1 encoding accepted; strict RFC 8032\n // rejects it, but the vendored ZIP-215 compliance vectors include this form in A/R bytes.\n if (!zip215 && x === 0n && isLastByteOdd)\n throw new Error('bad point: x==0, isLastByteOdd'); // x=0, x_0=1\n if (isLastByteOdd !== !!(x & 1n))\n x = mod(-x); // adjust sign of x coordinate\n return new Point(x, y, 1n, modP(x * y)); // Z=1, T=xy\n }\n static fromHex(hex, zip215) {\n return Point.fromBytes(hexToBytes(hex), zip215);\n }\n get x() {\n return this.toAffine().x;\n }\n get y() {\n return this.toAffine().y;\n }\n /** Checks if the point is valid and on-curve. */\n assertValidity() {\n const a = _a;\n const d = _d;\n const p = this;\n // Intentional stricter-than-on-curve policy: reject ZERO by default because many protocols\n // require a non-zero point, and silently accepting identity points is a common caller mistake.\n if (p.is0())\n throw new Error('bad point: ZERO');\n // Equation in affine coordinates: ax² + y² = 1 + dx²y²\n // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²\n const { X, Y, Z, T } = p;\n const X2 = modP(X * X); // X²\n const Y2 = modP(Y * Y); // Y²\n const Z2 = modP(Z * Z); // Z²\n const Z4 = modP(Z2 * Z2); // Z⁴\n const aX2 = modP(X2 * a); // aX²\n const left = modP(Z2 * (aX2 + Y2)); // (aX² + Y²)Z²\n const right = mod(Z4 + modP(d * modP(X2 * Y2))); // Z⁴ + dX²Y²\n if (left !== right)\n throw new Error('bad point: equation left != right (1)');\n // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T\n const XY = modP(X * Y);\n const ZT = modP(Z * T);\n if (XY !== ZT)\n throw new Error('bad point: equation left != right (2)');\n return this;\n }\n /** Equality check: compare points P&Q. */\n equals(other) {\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const { X: X2, Y: Y2, Z: Z2 } = apoint(other); // checks class equality\n return modP(X1 * Z2) === modP(X2 * Z1) && modP(Y1 * Z2) === modP(Y2 * Z1);\n }\n is0() {\n return this.equals(I);\n }\n /** Flip point over y coordinate. */\n negate() {\n return new Point(mod(-this.X), this.Y, this.Z, mod(-this.T));\n }\n /** Point doubling. Complete formula. Cost: `4M + 4S + 1*a + 6add + 1*2`. */\n double() {\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const a = _a;\n // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd\n const A = modP(X1 * X1);\n const B = modP(Y1 * Y1);\n const C = modP(2n * Z1 * Z1);\n const D = modP(a * A);\n const x1y1 = mod(X1 + Y1);\n const E = mod(modP(x1y1 * x1y1) - A - B);\n const G = mod(D + B);\n const F = mod(G - C);\n const H = mod(D - B);\n const X3 = modP(E * F);\n const Y3 = modP(G * H);\n const T3 = modP(E * H);\n const Z3 = modP(F * G);\n return new Point(X3, Y3, Z3, T3);\n }\n /** Point addition. Complete formula. Cost: `9M + 1*a + 1*d + 7add`. */\n add(other) {\n const { X: X1, Y: Y1, Z: Z1, T: T1 } = this;\n const { X: X2, Y: Y2, Z: Z2, T: T2 } = apoint(other); // doesn't check if other on-curve\n const a = _a;\n const d = _d;\n // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd\n const A = modP(X1 * X2);\n const B = modP(Y1 * Y2);\n const C = modP(modP(T1 * d) * T2);\n const D = modP(Z1 * Z2);\n const E = mod(modP(mod(X1 + Y1) * mod(X2 + Y2)) - A - B);\n const F = mod(D - C);\n const G = mod(D + C);\n const H = mod(B - modP(a * A));\n const X3 = modP(E * F);\n const Y3 = modP(G * H);\n const T3 = modP(E * H);\n const Z3 = modP(F * G);\n return new Point(X3, Y3, Z3, T3);\n }\n subtract(other) {\n return this.add(apoint(other).negate());\n }\n /**\n * Point-by-scalar multiplication. Safe mode requires `1 <= n < CURVE.n`.\n * Unsafe mode additionally permits `n = 0` and returns the identity point for that case.\n * Uses {@link wNAF} for base point.\n * Uses fake point to mitigate side-channel leakage.\n * @param n - scalar by which point is multiplied\n * @param safe - safe mode guards against timing attacks; unsafe mode is faster\n */\n multiply(n, safe = true) {\n // Mirror noble-curves: unsafe mode still validates scalar range first, but intentionally keeps\n // `n = 0` as the one extra accepted case used by verification-style callers.\n if (!safe && n === 0n)\n return I;\n arange(n, 1n, N);\n if (!safe && this.is0())\n return I;\n if (n === 1n)\n return this;\n if (this.equals(G))\n return wNAF(n).p;\n // init result point & fake point\n let p = I;\n let f = G;\n let d = this;\n // Safe mode always runs 256 iterations so ladder length can't leak the scalar's\n // leading zero bits; unsafe mode stops at the top set bit for speed.\n for (let i = 0; safe ? i < 256 : n > 0n; i++) {\n // if bit is present, add to point\n // if not present, add to fake, for timing safety\n if (n & 1n)\n p = p.add(d);\n else if (safe)\n f = f.add(d);\n d = d.double();\n n >>= 1n;\n }\n return p;\n }\n multiplyUnsafe(scalar) {\n return this.multiply(scalar, false);\n }\n /** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */\n toAffine() {\n const { X, Y, Z } = this;\n // Fast-path only for the identity point; all other inputs still go through inversion.\n if (this.equals(I))\n return { x: 0n, y: 1n };\n const iz = invert(Z, P);\n // (Z * Z^-1) must be 1, otherwise bad math\n if (modP(Z * iz) !== 1n)\n throw new Error('invalid inverse');\n // x = X*Z^-1; y = Y*Z^-1\n return { x: modP(X * iz), y: modP(Y * iz) };\n }\n toBytes() {\n const { x, y } = this.toAffine();\n const b = numTo32bLE(y);\n // store sign in first LE byte\n b[31] |= x & 1n ? 0x80 : 0;\n return b;\n }\n toHex() {\n return bytesToHex(this.toBytes());\n }\n clearCofactor() {\n return this.multiply(8n, false); // h = 8\n }\n isSmallOrder() {\n return this.clearCofactor().is0();\n }\n isTorsionFree() {\n // Multiply by big number N. We can't `mul(N)` because of checks. Instead, we `mul(N/2)*2+1`;\n // N is odd, so N/2 truncates and the final `add(this)` is always needed.\n return this.multiply(N / 2n, false)\n .double()\n .add(this)\n .is0();\n }\n}\n/** Generator / base point */\nconst G = new Point(Gx, Gy, 1n, mod(Gx * Gy));\n/** Identity / zero point */\nconst I = new Point(0n, 1n, 1n, 0n);\n// Static aliases\nPoint.BASE = G;\nPoint.ZERO = I;\nconst numTo32bLE = (num) => hexToBytes(padh(arange(num, 0n, B256), 64)).reverse();\n// Caller-enforced width: some sites require 32-byte RFC encodings, while others intentionally feed\n// wider SHA-512 output chunks through the same little-endian parser.\nconst bytesToNumberLE = (b) => BigInt('0x' + bytesToHex(Uint8Array.from(abytes(b)).reverse()));\nconst pow2 = (x, power) => {\n // pow2(x, 4) == x^(2^4)\n // Negative `power` values are not rejected here and currently leave `x` unchanged.\n let r = x;\n while (power-- > 0) {\n r = modP(r * r);\n }\n return r;\n};\n// prettier-ignore\nconst pow_2_252_3 = (x) => {\n const x2 = modP(x * x); // x^2, bits 1\n const b2 = modP(x2 * x); // x^3, bits 11\n const b4 = modP(pow2(b2, 2) * b2); // x^(2^4-1), bits 1111\n const b5 = modP(pow2(b4, 1) * x); // x^(2^5-1), bits 11111\n const b10 = modP(pow2(b5, 5) * b5); // x^(2^10-1)\n const b20 = modP(pow2(b10, 10) * b10); // x^(2^20-1)\n const b40 = modP(pow2(b20, 20) * b20); // x^(2^40-1)\n const b80 = modP(pow2(b40, 40) * b40); // x^(2^80-1)\n const b160 = modP(pow2(b80, 80) * b80); // x^(2^160-1)\n const b240 = modP(pow2(b160, 80) * b80); // x^(2^240-1)\n const b250 = modP(pow2(b240, 10) * b10); // x^(2^250-1)\n return modP(pow2(b250, 2) * x); // x^((p-5)/8), used by RFC8032 point decode\n};\nconst RM1 = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n; // 2^((p-1)/4) = sqrt(-1)\n// RFC8032 §5.1.3 square-root helper for point decompression. `value` is only meaningful when\n// `isValid` is true; callers are also expected to pass canonical field elements with non-zero `v`.\n// prettier-ignore\nconst uvRatio = (u, v) => {\n const v3 = modP(v * modP(v * v)); // v³\n const v7 = modP(modP(v3 * v3) * v); // v⁷\n const pow = pow_2_252_3(modP(u * v7)); // (uv⁷)^(p-5)/8\n let x = modP(u * modP(v3 * pow)); // (uv³)(uv⁷)^(p-5)/8\n const vx2 = modP(v * modP(x * x)); // vx²\n const root1 = x; // First root candidate\n const root2 = modP(x * RM1); // Second root candidate; RM1 is √-1\n const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root\n const useRoot2 = vx2 === mod(-u); // If vx² = -u, set x <-- x * 2^((p-1)/4)\n const noRoot = vx2 === mod(-u * RM1); // There is no valid root, vx² = -u√-1\n if (useRoot1)\n x = root1;\n if (useRoot2 || noRoot)\n x = root2; // We return root2 anyway, for const-time\n if ((mod(x) & 1n) === 1n)\n x = mod(-x); // edIsNegative\n return { isValid: useRoot1 || useRoot2, value: x };\n};\n// Reduce a little-endian byte string modulo the subgroup order `N` (RFC 8032's `L`); the `hash`\n// param name reflects the common caller shape, not an input restriction.\nconst modL_LE = (hash) => modN(bytesToNumberLE(hash));\n// RFC8032 5.1.5. Split the 64-byte hashed seed into the clamped scalar half and nonce prefix.\nconst hashedToExtK = (hashed) => {\n // slice creates a copy, unlike subarray\n const copy = snapshotBytes(hashed);\n const head = copy.slice(0, 32);\n head[0] &= 248; // Clamp bits: 0b1111_1000\n head[31] &= 127; // 0b0111_1111\n head[31] |= 64; // 0b0100_0000\n const prefix = copy.slice(32); // secret key \"prefix\"\n // RFC words this as `[s]B`; reducing the clamped little-endian scalar modulo `N` is equivalent\n // for base-point multiplication because `G` already has subgroup order `N`.\n const scalar = modL_LE(head);\n const point = G.multiply(scalar); // public key point\n const pointBytes = point.toBytes(); // point serialized to Uint8Array\n return { head, prefix, scalar, point, pointBytes };\n};\n// RFC8032 5.1.5; getPublicKey async, sync. Hash secret key and extract point.\nconst getExtendedPublicKeyAsync = (secretKey) => callHashAsync('sha512Async', abytes(secretKey, LEN, 'secretKey')).then(hashedToExtK);\nconst getExtendedPublicKey = (secretKey) => hashedToExtK(callHash('sha512', abytes(secretKey, LEN, 'secretKey')));\n/**\n * Creates a 32-byte Ed25519 public key from the RFC 8032 32-byte secret-key seed. Async.\n * @param secretKey - 32-byte RFC 8032 secret-key seed, not a 64-byte expanded secret key.\n * @returns 32-byte public key.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Derive the public key bytes for a newly generated signer secret.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const secretKey = ed.utils.randomSecretKey();\n * const publicKey = await ed.getPublicKeyAsync(secretKey);\n * ```\n */\nconst getPublicKeyAsync = (secretKey) => getExtendedPublicKeyAsync(secretKey).then((p) => p.pointBytes);\n/**\n * Creates a 32-byte Ed25519 public key from the RFC 8032 32-byte secret-key seed.\n * To use, set `hashes.sha512` first.\n * @param secretKey - 32-byte RFC 8032 secret-key seed, not a 64-byte expanded secret key.\n * @returns 32-byte public key.\n * @throws If synchronous SHA-512 has not been configured in `hashes`. {@link Error}\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Derive the public key entirely through the synchronous API.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const secretKey = ed.utils.randomSecretKey();\n * const publicKey = ed.getPublicKey(secretKey);\n * ```\n */\nconst getPublicKey = (secretKey) => getExtendedPublicKey(secretKey).pointBytes;\nconst hashFinishAsync = async (res) => res[1](await callHashAsync('sha512Async', res[0]));\nconst hashFinishSync = (res) => res[1](callHash('sha512', res[0]));\n// Code, shared between sync & async sign\nconst _sign = (e, rBytes, msg) => {\n const { pointBytes: A, scalar: s } = e;\n const r = modL_LE(rBytes); // r was created outside, reduce it modulo L\n // RFC 8032 5.1.6 allows r mod L = 0, and SUPERCOP ref10 accepts the resulting identity-point\n // signature.\n // We intentionally keep the safe multiply() rejection here so a miswired all-zero SHA-512 provider\n // fails loudly instead of silently producing a degenerate signature.\n const R = G.multiply(r).toBytes(); // R = [r]B\n const hashable = concatBytes(R, A, msg); // dom2(F, C) || R || A || PH(M)\n const finish = (hashed) => {\n // k = SHA512(dom2(F, C) || R || A || PH(M))\n const S = modN(r + modL_LE(hashed) * s); // S = (r + k * s) mod L; 0 <= s < l\n return abytes(concatBytes(R, numTo32bLE(S)), 64); // 64-byte sig: 32-byte encoded R point || 32-byte LE(S)\n };\n return [hashable, finish];\n};\n/**\n * Signs message using secret key. Async.\n * Follows RFC8032 5.1.6.\n * @param message - Message bytes to sign.\n * @param secretKey - 32-byte RFC 8032 secret-key seed, not a 64-byte expanded secret key.\n * @returns 64-byte Ed25519 signature.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Sign an arbitrary message with a fresh Ed25519 secret key.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const secretKey = ed.utils.randomSecretKey();\n * const message = new Uint8Array([1, 2, 3]);\n * const signature = await ed.signAsync(message, secretKey);\n * ```\n */\nconst signAsync = async (message, secretKey) => {\n const m = snapshotBytes(message, 'message');\n const e = await getExtendedPublicKeyAsync(secretKey);\n // r = SHA512(dom2(F, C) || prefix || PH(M)); then generate R, k, S and the signature.\n return hashFinishAsync(_sign(e, await callHashAsync('sha512Async', e.prefix, m), m));\n};\n/**\n * Signs message using secret key. To use, set `hashes.sha512` first.\n * Follows RFC8032 5.1.6.\n * @param message - Message bytes to sign.\n * @param secretKey - 32-byte RFC 8032 secret-key seed, not a 64-byte expanded secret key.\n * @returns 64-byte Ed25519 signature.\n * @throws If synchronous SHA-512 has not been configured in `hashes`. {@link Error}\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Use the sync API when you've wired a SHA-512 implementation yourself.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const secretKey = ed.utils.randomSecretKey();\n * const signature = ed.sign(new Uint8Array([1, 2, 3]), secretKey);\n * ```\n */\nconst sign = (message, secretKey) => {\n const m = snapshotBytes(message, 'message');\n const e = getExtendedPublicKey(secretKey);\n // r = SHA512(dom2(F, C) || prefix || PH(M)); then generate R, k, S and the signature.\n return hashFinishSync(_sign(e, callHash('sha512', e.prefix, m), m));\n};\n// Exported defaults favor ZIP-215 interoperability semantics; callers must opt into the stricter\n// branch with `{ zip215: false }`.\n// Preserves the exported ZIP-215 default for `{}` / `{ zip215: undefined }`, not just omitted opts.\nconst getZip215 = (options) => {\n if (options === null || typeof options !== 'object')\n throw new TypeError('expected valid options object');\n return options.zip215 ?? true;\n};\nconst _verify = (sig, msg, publicKey, options) => {\n sig = abytes(sig, 64, 'signature'); // Signature hex str/Bytes, must be 64 bytes\n msg = abytes(msg, undefined, 'message'); // Message hex str/Bytes\n publicKey = abytes(publicKey, LEN, 'publicKey');\n const zip215 = getZip215(options);\n // zip215=false keeps the library's stricter branch, which still canonicalizes `R` / `A` before\n // hashing and rejects small-order public keys earlier than pure RFC8032 text would require.\n const r = sig.subarray(0, LEN);\n const s = bytesToNumberLE(sig.subarray(LEN, 64)); // Decode second half as an integer S;\n let A, R, SB;\n let hashable = Uint8Array.of();\n let finished = false;\n try {\n // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.\n // zip215=true: 0 <= y < MASK (2^256 for ed25519)\n // zip215=false: 0 <= y < P (2^255-19 for ed25519)\n A = Point.fromBytes(publicKey, zip215);\n R = Point.fromBytes(r, zip215);\n SB = G.multiply(s, false); // 0 <= s < l is done inside\n // ZIP-215 accepts noncanonical / unreduced point encodings, so the challenge hash must use the\n // exact signature/public-key bytes rather than canonicalized re-encodings of the decoded points.\n hashable = concatBytes(r, publicKey, msg); // dom2(F, C) || R || A || PH(M)\n finished = true;\n }\n catch (error) { }\n const finish = (hashed) => {\n if (!finished)\n return false;\n // Policy: strict mode intentionally rejects all small-order public keys, even though the raw RFC\n // equation text is looser here. This matches libsodium and avoids weak / ambiguous verification\n // outcomes where unusual low-order public keys can make distinct key/signature combinations verify.\n if (!zip215 && A.isSmallOrder())\n return false;\n // k = SHA512(dom2(F, C) || R || A || PH(M))\n const k = modL_LE(hashed);\n const RkA = R.add(A.multiply(k, false));\n // Extended group equation\n // [8][S]B = [8]R + [8][k]A'\n return RkA.subtract(SB).clearCofactor().is0();\n };\n return [hashable, finish];\n};\n/**\n * Verifies a signature on message and public key. Async.\n * The implementation is based on RFC8032 5.1.7, but default opts use ZIP-215 semantics; pass\n * `{ zip215: false }` for the library's stricter branch.\n * @param signature - 64-byte signature.\n * @param message - Signed message bytes.\n * @param publicKey - 32-byte public key.\n * @param opts - Verification options. Defaults to ZIP-215 semantics. See {@link EdDSAVerifyOpts}.\n * @returns `true` when the signature is valid.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Verify the signature against the same message and derived public key.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const secretKey = ed.utils.randomSecretKey();\n * const message = new Uint8Array([1, 2, 3]);\n * const publicKey = await ed.getPublicKeyAsync(secretKey);\n * const signature = await ed.signAsync(message, secretKey);\n * const isValid = await ed.verifyAsync(signature, message, publicKey);\n * ```\n */\nconst verifyAsync = async (signature, message, publicKey, opts = {}) => hashFinishAsync(_verify(signature, message, publicKey, opts));\n/**\n * Verifies a signature on message and public key using the synchronous hash path.\n * The implementation is based on RFC8032 5.1.7, but default opts use ZIP-215 semantics; pass\n * `{ zip215: false }` for the library's stricter branch.\n * @param signature - 64-byte signature.\n * @param message - Signed message bytes.\n * @param publicKey - 32-byte public key.\n * @param opts - Verification options. Defaults to ZIP-215 semantics. See {@link EdDSAVerifyOpts}.\n * @returns `true` when the signature is valid.\n * @throws If synchronous SHA-512 has not been configured in `hashes`. {@link Error}\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Verify a signature entirely through the synchronous API.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const secretKey = ed.utils.randomSecretKey();\n * const message = new Uint8Array([1, 2, 3]);\n * const publicKey = ed.getPublicKey(secretKey);\n * const signature = ed.sign(message, secretKey);\n * const isValid = ed.verify(signature, message, publicKey);\n * ```\n */\nconst verify = (signature, message, publicKey, opts = {}) => hashFinishSync(_verify(signature, message, publicKey, opts));\n/**\n * Math, hex, byte helpers. Not in `utils` because utils share API with noble-curves.\n * Exposes the same low-level field-default `mod` reducer and non-CT `invert` helper used\n * internally.\n * @example\n * Convert bytes to a hex string with the low-level helper namespace.\n *\n * ```ts\n * const hex = etc.bytesToHex(new Uint8Array([1, 2, 3]));\n * ```\n */\nconst etc = /* @__PURE__ */ freeze({\n bytesToHex,\n hexToBytes,\n concatBytes,\n mod,\n invert,\n randomBytes,\n});\n/**\n * Hash implementations used by the synchronous API plus the default async WebCrypto provider.\n * Both slots are configurable API surface; wrapper helpers revalidate that providers still return\n * 64-byte SHA-512 digests.\n * @example\n * Provide a SHA-512 implementation before calling synchronous helpers.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const { publicKey } = ed.keygen();\n * ```\n */\nconst hashes = {\n sha512Async: async (message) => {\n const s = globalThis?.crypto?.subtle;\n if (!s)\n throw new Error('crypto.subtle must be defined, consider polyfill');\n return new Uint8Array(await s.digest('SHA-512', concatBytes(message)));\n },\n sha512: undefined,\n};\n// Returns the final 32-byte Ed25519 secret-key seed verbatim, generating fresh random bytes only\n// when omitted.\nconst randomSecretKey = (seed) => {\n return abytes(seed === undefined ? randomBytes() : seed, LEN, 'seed');\n};\n/**\n * Generates a secret/public keypair.\n * @param seed - Optional 32-byte Ed25519 secret-key seed, returned verbatim as `secretKey`.\n * @returns Keypair with `secretKey` and `publicKey`.\n * @throws If synchronous SHA-512 has not been configured in `hashes`. {@link Error}\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Generate a new keypair through the synchronous API after wiring SHA-512.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const { secretKey, publicKey } = ed.keygen();\n * ```\n */\nconst keygen = (seed) => {\n const secretKey = randomSecretKey(seed);\n const publicKey = getPublicKey(secretKey);\n return { secretKey, publicKey };\n};\n/**\n * Generates a secret/public keypair asynchronously.\n * @param seed - Optional 32-byte Ed25519 secret-key seed, returned verbatim as `secretKey`.\n * @returns Keypair with `secretKey` and `publicKey`.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Generate a new keypair through the asynchronous WebCrypto-backed path.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const { secretKey, publicKey } = await ed.keygenAsync();\n * ```\n */\nconst keygenAsync = async (seed) => {\n const secretKey = randomSecretKey(seed);\n const publicKey = await getPublicKeyAsync(secretKey);\n return { secretKey, publicKey };\n};\n/**\n * Ed25519-specific key utilities.\n * `utils.getExtendedPublicKey*` expose secret-derived internals (`head`, `prefix`, `scalar`, and\n * point objects), not just public-key bytes.\n * @example\n * Generate a new Ed25519 secret key and derive the matching public key.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const secretKey = ed.utils.randomSecretKey();\n * const publicKey = await ed.getPublicKeyAsync(secretKey);\n * ```\n */\nconst utils = /* @__PURE__ */ freeze({\n getExtendedPublicKeyAsync,\n getExtendedPublicKey,\n randomSecretKey,\n});\n// ## Precomputes\n// --------------\n// Fixed W=8 window: 33 windows (ceil(256/8) + 1, NOT 32 - see wNAF loop), 128 points per window.\n// Layout is grouped by window: each block stores the positive multiples `1*base .. 128*base` for\n// that window, and the extra `+1` window absorbs carries from signed-digit recoding.\nconst precompute = () => {\n const points = [];\n let p = G;\n let b;\n for (let w = 0; w < 33; w++) {\n b = p;\n points.push(b);\n for (let i = 1; i < 128; i++) {\n b = b.add(p);\n points.push(b);\n } // i=1, bc we skip 0\n p = b.double();\n }\n return points;\n};\nlet Gpows = undefined; // shared process-wide cache of base-point precomputes\n// Branch-based negate helper used for JS/JIT mitigation symmetry, not a strict constant-time claim.\nconst ctneg = (cnd, p) => {\n const n = p.negate();\n return cnd ? n : p;\n};\n/**\n * Precomputes give 12x faster getPublicKey(), 10x sign(), 2x verify() by\n * caching multiples of G (base point). Cache is stored in 32MB of RAM.\n * Any time `G.multiply` is done, precomputes are used.\n * Not used for getSharedSecret, which instead multiplies random pubkey `P.multiply`.\n *\n * w-ary non-adjacent form (wNAF) precomputation method is 10% slower than windowed method,\n * but takes 2x less RAM. RAM reduction is possible by utilizing `.subtract`.\n * Returns the real accumulator `p` plus a fake accumulator `f`; callers only care about `p`, while\n * `f` exists to keep similar work in zero-digit branches as a JS/JIT side-channel mitigation.\n *\n * !! Precomputes can be disabled by commenting-out call of the wNAF() inside Point#multiply().\n */\nconst wNAF = (n) => {\n const comp = Gpows || (Gpows = precompute());\n let p = I;\n let f = G; // f must be G, or could become I in the end\n for (let w = 0; w < 33; w++) {\n let wbits = Number(n & 255n); // extract W=8 bits.\n n >>= 8n; // shift number by W=8 bits.\n // We use negative indexes to reduce size of precomputed table by 2x.\n // Instead of needing precomputes 0..256, we only calculate them for 0..128.\n // If an index > 128 is found, we do (256-index) - where 256 is next window.\n // Naive: index +127 => 127, +224 => 224\n // Optimized: index +127 => 127, +224 => 256-32\n if (wbits > 128) {\n wbits -= 256;\n n += 1n;\n }\n const off = w * 128; // offset of this window's block; also the fake-add index\n const offP = off + Math.abs(wbits) - 1; // real-add index; both offsets always evaluated\n const isOddW = w % 2 !== 0; // conditions, evaluate both; alternates fake-add sign per window\n const isNeg = wbits < 0;\n if (wbits === 0) {\n // wbits == 0 means the real index would be I: can't add it. Add window offset `off` instead.\n f = f.add(ctneg(isOddW, comp[off])); // bits are 0: add garbage to fake point\n }\n else {\n p = p.add(ctneg(isNeg, comp[offP])); // bits are 1: add to result point\n }\n }\n if (n !== 0n)\n throw new Error('invalid wnaf');\n return { p, f }; // return both real and fake points for JIT/leakage-shape symmetry\n};\n// !! Remove the export to easily use in REPL / browser console\nexport { etc, getPublicKey, getPublicKeyAsync, hash, hashes, keygen, keygenAsync, Point, sign, signAsync, utils, verify, verifyAsync, };\n","/**\n * The public keys this build of the SDK will accept licence signatures from.\n *\n * **This file contains public keys only.** BroadPaper's private signing key\n * lives in the licence issuer's secret store and is never in this repository,\n * never in the npm package and never in a browser bundle. Publishing the\n * public half is the point: it is what lets a licence be checked with no\n * network call.\n *\n * Add a production key with:\n *\n * node scripts/licence-keys.mjs --production --key-id bp-1\n *\n * which prints the private key once, for the operator to paste into the\n * issuer's configuration, and writes the public half into this array.\n *\n * The list is an allowlist, so it is also the rotation mechanism: issue with a\n * new `keyId`, ship an SDK release trusting both, and drop the old entry once\n * every licence signed with it has expired. Licences carry their `keyId` inside\n * the signed payload, so an attacker cannot point one at a different key.\n *\n * It starts empty on purpose. A key here is trusted by every copy of the SDK in\n * the world, including production installs, which is exactly why a development\n * key must never be added to it — development keys are supplied at runtime\n * instead, through `configure({ trustedKeys })` or `BROADPAPER_TRUSTED_KEYS`,\n * so a licence signed in development cannot be honoured by a production build.\n */\nimport type { TrustedKey } from \"./types.js\";\n\nexport const TRUSTED_KEYS: readonly TrustedKey[] = [\n { keyId: \"bp-2026\", publicKey: \"woKmWyIazae7SpGhi4dwA7zNK1lWdboq88Rl5xscTs4\", note: \"production, generated 2026-09-08\" }\n];\n","/**\n * The licence certificate and the states it can be in.\n *\n * A BroadPaper licence is a signed certificate, not a secret. It says who\n * bought what and until when, BroadPaper signs it, and the SDK checks that\n * signature with a public key compiled into the package. Nothing here talks to\n * a network, reads a machine identifier or writes a file: a licence that is\n * valid on a laptop with no route to the internet is valid, full stop.\n */\n\n/**\n * Which licence was bought. Not a feature gate — both plans unlock exactly the\n * same software. The difference is who the resulting application may be put in\n * front of, which is a contractual matter and is presented as one in the\n * account area and the licence agreement.\n *\n * These are the `id`s in `shared/plans.json`, deliberately: that file is the\n * one machine-readable statement of the commercial model, and a certificate\n * that quotes a different vocabulary from the thing that priced it is a\n * certificate somebody eventually has to write a mapping table for.\n */\nexport type Plan = \"internal\" | \"saas\";\n\n/**\n * How the licence is held.\n *\n * `subscription` is a term: the right to use the software ends with the term,\n * and so does the right to updates. It is the only thing sold today.\n *\n * `perpetual` is reserved. It would mean the right to use never ends, while\n * the right to updates still does — `validUntil` null, `updatesUntil` set. The\n * field exists now so that offering one later is a change to what the issuer\n * writes rather than a change to the certificate format, which would mean\n * reissuing every licence in the field. **This SDK does not honour one**: see\n * `readPayload` in `format.ts` for why refusing is the only safe answer.\n */\nexport type LicenseType = \"subscription\" | \"perpetual\";\n\n/** The product a licence is for. Present so one signing key can serve more later. */\nexport const PRODUCT = \"broadpaper-sdk\";\n\n/**\n * The signed payload.\n *\n * `organisationId` is the durable identifier of the buying organisation — a\n * Clerk organisation id — rather than an email address, because people change\n * addresses and organisations outlive their founders. It is *not* the Creem\n * customer id, which identifies the same buyer to the payment processor and is\n * a different string; the API keeps both, and naming this one for the\n * organisation is what stops the two being confused at a glance.\n *\n * Times are epoch **seconds**, not milliseconds and not ISO strings. The\n * certificate is written by `Utf8JsonWriter` in C# and read by `JSON.parse` in\n * TypeScript, and an integer cannot disagree about a timezone suffix or a\n * fractional second the way two date serialisers can — which matters more here\n * than anywhere, because the two halves only find out they disagree when a\n * customer's licence is rejected in the field.\n *\n * Field order is load-bearing on the issuing side only: `encodeSigningInput`\n * serialises this object, and `LicenceSigner.Payload` writes the same keys in\n * the same order so a certificate is byte-identical whichever issued it.\n * Verification never re-serialises — it checks the signature over the text as\n * received — so an unknown field from a later BroadPaper is carried through\n * rather than rejected.\n */\nexport interface LicensePayload {\n /**\n * Payload schema version. Bumped only when the meaning of a field changes,\n * never to add one: `readPayload` keeps fields it does not know about, so a\n * later BroadPaper can extend the certificate without older SDKs refusing it.\n */\n schemaVersion: 1;\n /** Which signing key signed this. Lets keys be rotated without reissuing everything. */\n keyId: string;\n /**\n * BroadPaper's own identifier for *this certificate*, `lic_…`.\n *\n * One per issuance, so a renewal or an upgrade carries a new one and the\n * document it produced can be dated from it. The buyer is identified by\n * `organisationId`, which does not change.\n */\n licenseId: string;\n /** The licensed organisation's durable id. A Clerk organisation id. */\n organisationId: string;\n /** The organisation's name, for display in warnings and PDF metadata. */\n organisationName: string;\n product: typeof PRODUCT;\n plan: Plan;\n licenseType: LicenseType;\n /** Epoch seconds. */\n issuedAt: number;\n /**\n * When the right to *use* the software ends, in epoch seconds.\n *\n * Null means never, which only a perpetual licence says. A subscription\n * always carries a date.\n */\n validUntil: number | null;\n /**\n * When the right to *updates* ends, in epoch seconds.\n *\n * For a subscription this equals `validUntil` and nothing reads it: the term\n * ends, and both rights end with it. It is separate from `validUntil` because\n * for a perpetual licence the two genuinely differ, and that is the whole\n * reason the field is here before anything consults it.\n */\n updatesUntil: number;\n}\n\n/**\n * Why a licence is not being honoured, or how it is being honoured.\n *\n * These are deliberately coarse. A developer needs to know whether their PDFs\n * will carry the evaluation mark and, if so, what to do about it; a taxonomy of\n * eleven parse failures helps nobody.\n */\nexport type LicenseState =\n /** No licence was configured. The SDK works; PDFs carry the evaluation mark. */\n | \"unlicensed\"\n /** A licence was configured but could not be read, or its signature is wrong. */\n | \"invalid\"\n /** Signed by a key this build of the SDK does not trust. */\n | \"untrusted\"\n /** For a different product, or a certificate this SDK is too old to honour. */\n | \"unsupported\"\n /** Valid, signed, and inside its term. */\n | \"active\"\n /** Past `validUntil` but inside the grace period: honoured, and warned about. */\n | \"grace\"\n /** Past `validUntil` and past the grace period. */\n | \"expired\";\n\n/** The outcome of checking a licence. Everything the SDK needs to decide. */\nexport interface LicenseStatus {\n state: LicenseState;\n /** True when PDFs render clean. `active` and `grace` only. */\n licensed: boolean;\n /** The payload, when one could be read and verified. */\n payload: LicensePayload | null;\n /** Which licence was bought, when it is being honoured. */\n plan: Plan | null;\n /** When the right to use ends, when known. Null for a licence with no end. */\n validUntil: Date | null;\n /** Days until `validUntil`; negative once expired. Null when there is no end date. */\n daysRemaining: number | null;\n /**\n * A developer-facing sentence. Always present for a state that is not\n * `active`, so callers can log it without composing their own prose.\n */\n message: string | null;\n}\n\n/** A public key this build of the SDK will accept signatures from. */\nexport interface TrustedKey {\n /** Matches `keyId` in the payload. */\n keyId: string;\n /** The raw 32-byte Ed25519 public key, base64url or base64. */\n publicKey: string;\n /** Free text for the key's provenance. Never displayed to end users. */\n note?: string;\n}\n","/**\n * Offline licence verification.\n *\n * Everything here is local: a signature check against a compiled-in public key\n * and a comparison against the clock. There is no activation call, no licence\n * server and nothing to be offline from. That is a deliberate product decision\n * as much as a technical one — a report renderer that stops working because a\n * key server is down is a report renderer nobody puts in a payroll run.\n *\n * The failure modes are all *soft*. An unreadable licence never throws out of a\n * render; it produces a status whose `message` says what is wrong, and the PDF\n * comes out carrying the evaluation mark.\n */\nimport { verifyAsync } from \"@noble/ed25519\";\nimport { base64UrlToBytes, utf8ToBytes } from \"./encoding.js\";\nimport { LicenseFormatError, parseLicense } from \"./format.js\";\nimport { TRUSTED_KEYS } from \"./trusted-keys.js\";\nimport { PRODUCT, type LicensePayload, type LicenseStatus, type TrustedKey } from \"./types.js\";\n\n/**\n * How long an expired licence keeps working.\n *\n * A renewal that is a week late is an accounts payable problem, not a reason to\n * stamp a customer's month-end reports. Thirty days is long enough to cover a\n * card expiring over a holiday and short enough that it is not a second licence\n * term.\n */\nexport const DEFAULT_GRACE_PERIOD_DAYS = 30;\n\nconst DAY_MS = 86_400_000;\n\nexport interface VerifyOptions {\n /** Fixed clock. Tests and deterministic renders pass one. */\n now?: Date;\n /** Extra keys to trust, on top of the ones built into this SDK. */\n trustedKeys?: readonly TrustedKey[];\n /** Overrides {@link DEFAULT_GRACE_PERIOD_DAYS}. */\n gracePeriodDays?: number;\n}\n\n/** The status of a caller that supplied no licence at all. */\nexport function unlicensed(): LicenseStatus {\n return {\n state: \"unlicensed\",\n licensed: false,\n payload: null,\n plan: null,\n validUntil: null,\n daysRemaining: null,\n message:\n \"No BroadPaper licence is configured, so PDFs carry the evaluation watermark. Everything else works; see https://www.broadpaper.com/docs/guide/licensing.\"\n };\n}\n\nfunction failure(state: LicenseStatus[\"state\"], message: string, payload: LicensePayload | null = null): LicenseStatus {\n return {\n state,\n licensed: false,\n payload,\n plan: null,\n validUntil: payload?.validUntil != null ? new Date(payload.validUntil * 1000) : null,\n daysRemaining: null,\n message\n };\n}\n\n/**\n * Checks a licence string and reports what it entitles the caller to.\n *\n * Never throws for a bad licence: a malformed string, a forged signature and an\n * expired term are all ordinary answers, and a render is not the place to\n * discover that a config file has a typo in it.\n */\nexport async function verifyLicense(license: string | null | undefined, options: VerifyOptions = {}): Promise<LicenseStatus> {\n if (!license || !license.trim()) return unlicensed();\n\n let parsed;\n try {\n parsed = parseLicense(license);\n } catch (e) {\n if (e instanceof LicenseFormatError) {\n return failure(\n e.kind,\n e.kind === \"unsupported\"\n ? `This BroadPaper licence needs a newer version of the SDK (${e.message}). Update @broadpaper/* or the PDF will carry the evaluation watermark.`\n : `The BroadPaper licence could not be read (${e.message}), so PDFs carry the evaluation watermark.`\n );\n }\n /* c8 ignore next -- parseLicense only throws LicenseFormatError */\n throw e;\n }\n\n const { payload } = parsed;\n if (payload.product !== PRODUCT) {\n return failure(\n \"invalid\",\n `This licence is for ${JSON.stringify(payload.product)}, not the BroadPaper SDK, so PDFs carry the evaluation watermark.`,\n payload\n );\n }\n\n const key = findKey(payload.keyId, options.trustedKeys);\n if (!key) {\n return failure(\n \"untrusted\",\n `This BroadPaper licence was signed with key ${JSON.stringify(payload.keyId)}, which this build does not trust. ` +\n \"A licence issued for development is not honoured by a production build; check BROADPAPER_LICENSE points at the right one.\",\n payload\n );\n }\n\n let signatureOk = false;\n try {\n signatureOk = await verifyAsync(parsed.signature, utf8ToBytes(parsed.signedText), base64UrlToBytes(key.publicKey));\n } catch {\n // A malformed public key or a point that is not on the curve. Either way\n // this licence is not going to verify, and a render must not fail over it.\n signatureOk = false;\n }\n if (!signatureOk) {\n return failure(\"invalid\", \"This BroadPaper licence failed its signature check — it has been altered or truncated. PDFs carry the evaluation watermark.\", payload);\n }\n\n const now = options.now ?? new Date();\n\n // A licence with no end date never expires, so there is no clock to consult.\n // Nothing sold today issues one — `readPayload` refuses the only licence type\n // that would — but the field is nullable, and a null that fell through to the\n // arithmetic below would come out as 1970 and watermark a valid licence.\n if (payload.validUntil === null) {\n return { state: \"active\", licensed: true, payload, plan: payload.plan, validUntil: null, daysRemaining: null, message: null };\n }\n\n const validUntil = new Date(payload.validUntil * 1000);\n const graceDays = options.gracePeriodDays ?? DEFAULT_GRACE_PERIOD_DAYS;\n const msRemaining = validUntil.getTime() - now.getTime();\n const daysRemaining = Math.floor(msRemaining / DAY_MS);\n\n if (msRemaining > 0) {\n return {\n state: \"active\",\n licensed: true,\n payload,\n plan: payload.plan,\n validUntil,\n daysRemaining,\n message: null\n };\n }\n\n if (msRemaining > -graceDays * DAY_MS) {\n const daysOver = Math.max(1, Math.ceil(-msRemaining / DAY_MS));\n return {\n state: \"grace\",\n licensed: true,\n payload,\n plan: payload.plan,\n validUntil,\n daysRemaining,\n message:\n `The BroadPaper licence for ${payload.organisationName} expired ${daysOver} day${daysOver === 1 ? \"\" : \"s\"} ago and is inside its ${graceDays}-day grace period. ` +\n \"Renew it and copy the new licence from your account, or PDFs will start carrying the evaluation watermark.\"\n };\n }\n\n return failure(\n \"expired\",\n `The BroadPaper licence for ${payload.organisationName} expired on ${validUntil.toISOString().slice(0, 10)} and its ${graceDays}-day grace period has passed, ` +\n \"so PDFs carry the evaluation watermark. Renewing issues a new licence in your BroadPaper account.\",\n payload\n );\n}\n\nfunction findKey(keyId: string, extra: readonly TrustedKey[] | undefined): TrustedKey | undefined {\n // Runtime keys are searched first so a development key can shadow a built-in\n // one of the same name without a rebuild.\n return extra?.find((k) => k.keyId === keyId) ?? TRUSTED_KEYS.find((k) => k.keyId === keyId);\n}\n","/**\n * Configuring BroadPaper once, for the life of the process.\n *\n * import { BroadPaper } from \"@broadpaper/forme\";\n * BroadPaper.configure({ license: process.env.BROADPAPER_LICENSE });\n *\n * The licence is not a credential, so this is not a secrets API: it is the same\n * shape of thing as setting a locale. A browser bundle that carries the licence\n * string in plain text is fine — the string is a signed certificate, and\n * possessing it grants nothing beyond what its payload already says.\n *\n * Configuration is deliberately process-global rather than an argument to every\n * render. Threading a licence through `renderPdf`, the render service, the\n * batch endpoint, the .NET client and every future export path is exactly the\n * kind of plumbing that ends with one path quietly forgetting it, and a\n * customer who has paid discovering a watermark in production.\n *\n * The store hangs off a `Symbol.for` key rather than a module-level variable so\n * that two copies of this package in one dependency tree — the usual result of\n * a mixed-version install — still agree about the licence.\n */\nimport { unlicensed, verifyLicense, type VerifyOptions } from \"./verify.js\";\nimport type { LicenseStatus, TrustedKey } from \"./types.js\";\n\nexport interface BroadPaperConfig {\n /**\n * The licence string, `BP1.…`. Read from `BROADPAPER_LICENSE` when this is\n * not set and the runtime has environment variables.\n */\n license?: string | null;\n /**\n * Public keys to trust in addition to the ones built into the SDK. This is\n * how a development licence is honoured on a developer's machine without a\n * development key ever being trusted by a production build.\n */\n trustedKeys?: readonly TrustedKey[];\n /** Overrides the 30-day post-expiry grace period. Mostly for tests. */\n gracePeriodDays?: number;\n /** Where licence warnings go. Defaults to `console.warn`. */\n logger?: ((message: string) => void) | null;\n}\n\ninterface Store {\n config: BroadPaperConfig;\n /** Memoised by the licence string that produced it. */\n cache: { key: string; status: Promise<LicenseStatus> } | null;\n /** Messages already logged, so a hundred renders do not print a hundred lines. */\n logged: Set<string>;\n}\n\nconst STORE_KEY = Symbol.for(\"broadpaper.license.store\");\n\nfunction store(): Store {\n const g = globalThis as Record<symbol, unknown>;\n let s = g[STORE_KEY] as Store | undefined;\n if (!s) {\n s = { config: {}, cache: null, logged: new Set() };\n g[STORE_KEY] = s;\n }\n return s;\n}\n\n/**\n * Sets the licence and any other SDK-wide options. Call it once, at startup.\n *\n * Successive calls merge, so a host can set the licence in one place and the\n * grace period in another; passing `license: null` clears it.\n */\nexport function configure(config: BroadPaperConfig): void {\n const s = store();\n s.config = { ...s.config, ...config };\n s.cache = null;\n s.logged.clear();\n}\n\n/** What {@link configure} has been given, plus whatever the environment supplies. */\nexport function getConfig(): BroadPaperConfig {\n return { ...store().config };\n}\n\n/** Forgets the configuration entirely. Exists for tests. */\nexport function resetConfig(): void {\n const g = globalThis as Record<symbol, unknown>;\n delete g[STORE_KEY];\n}\n\n/**\n * `BroadPaper.configure({ … })`, for hosts that prefer a namespace to a bare\n * function. Both are the same store.\n */\nexport const BroadPaper = { configure, getConfig };\n\nfunction env(name: string): string | undefined {\n // Node, Deno and bundlers that inline `process.env` all satisfy this; a\n // browser without a shim simply has no environment, which is not an error.\n const p = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n const value = p?.env?.[name];\n return value && value.trim() ? value : undefined;\n}\n\n/**\n * Keys trusted in addition to the built-in ones, from configuration and from\n * `BROADPAPER_TRUSTED_KEYS` — a JSON array of `{ keyId, publicKey }`.\n *\n * A syntax error there is reported rather than swallowed: someone setting that\n * variable is doing so on purpose, and silently ignoring it would present as\n * \"my development licence is not being honoured\" with nothing to go on.\n */\nfunction trustedKeysFromEnv(): readonly TrustedKey[] {\n const raw = env(\"BROADPAPER_TRUSTED_KEYS\");\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) throw new Error(\"expected a JSON array\");\n return parsed.map((entry, i) => {\n const k = entry as Record<string, unknown>;\n if (typeof k?.keyId !== \"string\" || typeof k?.publicKey !== \"string\") throw new Error(`entry ${i} needs keyId and publicKey`);\n return { keyId: k.keyId, publicKey: k.publicKey };\n });\n } catch (e) {\n warn(`BROADPAPER_TRUSTED_KEYS could not be read (${(e as Error).message}); it is being ignored.`);\n return [];\n }\n}\n\n/** Logs a message once, whatever it takes to reach the developer. */\nexport function warn(message: string): void {\n const s = store();\n if (s.logged.has(message)) return;\n s.logged.add(message);\n const logger = s.config.logger;\n if (logger === null) return;\n const line = `[BroadPaper] ${message}`;\n if (logger) logger(line);\n else console.warn(line);\n}\n\nexport interface ResolveOptions extends VerifyOptions {\n /** A licence for this call only, overriding the configured one. */\n license?: string | null;\n}\n\n/**\n * The licence status for the current configuration.\n *\n * Memoised on the licence string, because every PDF asks and a signature check\n * per page of a five-hundred-page batch is waste. `configure` clears it, and a\n * per-call `license` bypasses it.\n *\n * Whatever the answer, any developer-facing message is logged once. That is the\n * only thing the SDK does that a caller did not ask for, and it is the\n * difference between a developer seeing \"your licence expired\" and a developer\n * seeing an unexplained watermark.\n */\nexport async function resolveLicenseStatus(options: ResolveOptions = {}): Promise<LicenseStatus> {\n const s = store();\n const config = s.config;\n const license = options.license !== undefined ? options.license : config.license ?? env(\"BROADPAPER_LICENSE\") ?? null;\n const trustedKeys = [...(options.trustedKeys ?? []), ...(config.trustedKeys ?? []), ...trustedKeysFromEnv()];\n const gracePeriodDays = options.gracePeriodDays ?? config.gracePeriodDays;\n\n if (!license) {\n const status = unlicensed();\n if (status.message) warn(status.message);\n return status;\n }\n\n const verify = (): Promise<LicenseStatus> =>\n verifyLicense(license, { ...(options.now ? { now: options.now } : {}), trustedKeys, ...(gracePeriodDays !== undefined ? { gracePeriodDays } : {}) }).then((status) => {\n if (status.message) warn(status.message);\n return status;\n });\n\n // A fixed clock is a test or a deterministic render; caching across different\n // clocks would make the grace-period boundary depend on call order.\n if (options.now || options.license !== undefined) return verify();\n\n const key = `${license}|${trustedKeys.map((k) => k.keyId).join(\",\")}|${gracePeriodDays ?? \"\"}`;\n if (s.cache?.key !== key) s.cache = { key, status: verify() };\n return s.cache.status;\n}\n","/**\n * The evaluation mark.\n *\n * This is the only thing an unlicensed BroadPaper does differently. Every\n * block, both PDF backends, the designer, data binding, pagination and the\n * render service behave identically with and without a licence; what changes is\n * that the file says, on every page, that it was produced with an evaluation\n * copy.\n *\n * It is drawn to be unmistakable in a document review and harmless to a\n * developer evaluating the product: a light diagonal line across the page,\n * behind nothing and over everything, at an opacity that leaves the report\n * entirely readable. Making the output illegible would only push people towards\n * evaluating something else.\n *\n * Each backend draws the spec with its own primitives — the Forme engine has a\n * page-native watermark node, Chromium gets a printed overlay — because a\n * single drawing implementation would mean one of them post-processing a file\n * the other had already finished, and a stamping pass that can be skipped is a\n * stamping pass that eventually is.\n */\nimport { resolveLicenseStatus, type ResolveOptions } from \"./config.js\";\nimport type { LicenseStatus } from \"./types.js\";\n\nexport interface WatermarkSpec {\n text: string;\n /** Points. The engines size the mark from this, not from the page. */\n fontSize: number;\n /** Degrees, anticlockwise from horizontal. */\n angle: number;\n /** Hex, without alpha. */\n color: string;\n /** 0–1. */\n opacity: number;\n}\n\n/**\n * The mark itself.\n *\n * No dashes or typographic punctuation: the standard PDF faces carry no em\n * dash, and a theme that names a font the engine does not have falls back to\n * them, which turned \"BroadPaper — Evaluation Copy\" into \"BroadPaper\n * Evaluation Copy\" in half the documents and a question mark in the rest.\n */\nexport const EVALUATION_WATERMARK: WatermarkSpec = {\n text: \"BroadPaper Evaluation Copy\",\n fontSize: 44,\n angle: -35,\n color: \"#c8102e\",\n opacity: 0.12\n};\n\n/**\n * The mark a render should carry, or null when the licence says none.\n *\n * Backends call this rather than reading the licence status themselves, so\n * \"licensed\" and \"no watermark\" cannot drift apart.\n */\nexport async function resolveWatermark(options: ResolveOptions = {}): Promise<WatermarkSpec | null> {\n const status = await resolveLicenseStatus(options);\n return watermarkFor(status);\n}\n\n/** The pure half of {@link resolveWatermark}, for callers that already have a status. */\nexport function watermarkFor(status: LicenseStatus): WatermarkSpec | null {\n return status.licensed ? null : EVALUATION_WATERMARK;\n}\n\n/**\n * CSS that paints the mark on every `.bp-page` of a rendered document.\n *\n * Used by the Chromium backend and by the designer's print path — the two\n * places a PDF is produced by a browser rather than by the engine. `position:\n * fixed` would put it on the viewport rather than on each page, so it is an\n * absolutely positioned pseudo-element on the page box, which prints once per\n * sheet.\n *\n * `print-color-adjust` matters: without it Chromium drops the mark from the\n * printed file exactly as it drops any other background colour.\n */\nexport function watermarkCss(spec: WatermarkSpec = EVALUATION_WATERMARK): string {\n const text = spec.text.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n return [\n \".bp-page{position:relative;}\",\n \".bp-page::after{\",\n `content:\"${text}\";`,\n \"position:absolute;inset:0;\",\n \"display:flex;align-items:center;justify-content:center;\",\n \"pointer-events:none;z-index:2147483647;\",\n `transform:rotate(${spec.angle}deg);`,\n \"font-family:Helvetica,Arial,sans-serif;font-weight:700;letter-spacing:0.04em;white-space:nowrap;\",\n `font-size:${spec.fontSize}pt;color:${spec.color};opacity:${spec.opacity};`,\n \"-webkit-print-color-adjust:exact;print-color-adjust:exact;\",\n \"}\"\n ].join(\"\");\n}\n\n/**\n * The PDF Producer string for a render.\n *\n * Licensed output records the licence id. It is not a secret — it identifies a\n * customer's licence, not their account — and having it in the file means a\n * document that turns up somewhere it should not can be traced back to the\n * licence that produced it without any of the tracking a phone-home would need.\n */\nexport function producerString(status: LicenseStatus): string {\n if (!status.licensed || !status.payload) return \"BroadPaper (evaluation)\";\n return `BroadPaper (${status.payload.licenseId})`;\n}\n","import { lookup } from \"node:dns/promises\";\nimport { isIP } from \"node:net\";\n\nexport interface NetworkPolicy {\n /**\n * Hostnames (or `*.example.com` wildcards, or `*`) the renderer may fetch\n * assets from. `data:` URLs are always allowed. Default: none.\n */\n allowedHosts?: string[];\n /** Block private / loopback / link-local address ranges even for allowed hosts. Default true. */\n blockPrivateNetworks?: boolean;\n /** Maximum number of network requests per render. Default 200. */\n maxRequests?: number;\n}\n\nconst PRIVATE_V4 = [\n [/^10\\./, \"10/8\"],\n [/^127\\./, \"loopback\"],\n [/^169\\.254\\./, \"link-local\"],\n [/^172\\.(1[6-9]|2\\d|3[01])\\./, \"172.16/12\"],\n [/^192\\.168\\./, \"192.168/16\"],\n [/^0\\./, \"0/8\"],\n [/^100\\.(6[4-9]|[7-9]\\d|1[01]\\d|12[0-7])\\./, \"CGNAT\"]\n] as const;\n\nexport function isPrivateAddress(ip: string): boolean {\n const kind = isIP(ip);\n if (kind === 4) return PRIVATE_V4.some(([re]) => re.test(ip));\n if (kind === 6) {\n const lower = ip.toLowerCase();\n if (lower === \"::1\" || lower === \"::\") return true;\n if (lower.startsWith(\"fe80:\") || lower.startsWith(\"fc\") || lower.startsWith(\"fd\")) return true;\n const mapped = /^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/.exec(lower);\n if (mapped) return isPrivateAddress(mapped[1]!);\n return false;\n }\n return false;\n}\n\nexport function hostAllowed(host: string, allowed: string[] | undefined): boolean {\n if (!allowed || allowed.length === 0) return false;\n const h = host.toLowerCase();\n return allowed.some((pattern) => {\n const p = pattern.toLowerCase();\n if (p === \"*\") return true;\n if (p.startsWith(\"*.\")) return h === p.slice(2) || h.endsWith(p.slice(1));\n return h === p;\n });\n}\n\nexport interface RequestDecision {\n allow: boolean;\n reason?: string;\n}\n\n/**\n * Decides whether the headless browser may perform a request. Resolves DNS so\n * that a public hostname pointing at a private address is still blocked.\n */\nexport async function decideRequest(url: string, policy: NetworkPolicy, counter: { count: number }): Promise<RequestDecision> {\n if (url.startsWith(\"data:\") || url === \"about:blank\") return { allow: true };\n let u: URL;\n try {\n u = new URL(url);\n } catch {\n return { allow: false, reason: \"invalid URL\" };\n }\n if (u.protocol !== \"http:\" && u.protocol !== \"https:\") return { allow: false, reason: `scheme ${u.protocol} not allowed` };\n if (++counter.count > (policy.maxRequests ?? 200)) return { allow: false, reason: \"request limit exceeded\" };\n if (!hostAllowed(u.hostname, policy.allowedHosts)) return { allow: false, reason: `host ${u.hostname} not in allow-list` };\n if (policy.blockPrivateNetworks !== false) {\n const host = u.hostname.replace(/^\\[|\\]$/g, \"\");\n if (host === \"localhost\" || host.endsWith(\".localhost\") || host.endsWith(\".internal\")) return { allow: false, reason: \"private host\" };\n if (isIP(host)) {\n if (isPrivateAddress(host)) return { allow: false, reason: \"private address\" };\n } else {\n try {\n const results = await lookup(host, { all: true });\n if (results.some((r) => isPrivateAddress(r.address))) return { allow: false, reason: \"resolves to a private address\" };\n } catch {\n return { allow: false, reason: \"DNS lookup failed\" };\n }\n }\n }\n return { allow: true };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\nimport type { Browser, BrowserContext } from \"playwright-core\";\nimport type { DataSource, ReportData, ReportTemplate, Theme } from \"@broadpaper/core\";\nimport { producerString, resolveLicenseStatus, watermarkFor, type LicenseStatus } from \"@broadpaper/license\";\nimport { decideRequest, type NetworkPolicy } from \"./ssrf.js\";\nimport { stampWatermark } from \"./watermark.js\";\nimport type { RuntimeRenderOutput } from \"../runtime/index.js\";\n\nexport interface PdfMetadata {\n title?: string;\n author?: string;\n subject?: string;\n keywords?: string[];\n /** Creation date. Defaults to `now`. */\n creationDate?: Date;\n}\n\nexport interface RenderPdfOptions {\n template: ReportTemplate | { schemaVersion: number; [k: string]: unknown };\n data?: ReportData;\n theme?: Partial<Theme>;\n dataSources?: DataSource[];\n /** Fixed clock for deterministic output. */\n now?: Date;\n locale?: string;\n currency?: string;\n timeZone?: string;\n metadata?: PdfMetadata;\n /**\n * JavaScript source for a browser bundle that registers custom blocks:\n * it must call `BroadPaper.registerBlocks([...])`. Built by the host with its\n * own bundler from `@broadpaper/core` block definitions.\n */\n customBlocksScript?: string;\n network?: NetworkPolicy;\n /** Per-render timeout in ms. Default 60000. */\n timeoutMs?: number;\n /** Refuse documents longer than this. Default 500. */\n maxPages?: number;\n /** Chromium tagged (accessible) PDF. Default true. */\n tagged?: boolean;\n /** PDF/A-like outline generation from headings. Default true. */\n outline?: boolean;\n /** Attach the runtime from a custom path (testing). */\n runtimePath?: string;\n /**\n * A licence for this render only, overriding whatever `configure` was given.\n * A service rendering for one organisation should configure once at startup\n * instead; this is for a host that renders on behalf of several.\n */\n license?: string | null;\n}\n\nexport interface RenderPdfResult {\n pdf: Buffer;\n pages: number;\n warnings: RuntimeRenderOutput[\"warnings\"];\n /** Wall-clock render time in ms. */\n durationMs: number;\n}\n\nexport class PdfRenderError extends Error {\n constructor(\n message: string,\n public readonly code: \"TIMEOUT\" | \"TOO_MANY_PAGES\" | \"RUNTIME\" | \"BROWSER\"\n ) {\n super(message);\n this.name = \"PdfRenderError\";\n }\n}\n\nlet runtimeCache: string | null = null;\n\nasync function loadRuntime(path?: string): Promise<string> {\n if (path) return readFile(path, \"utf8\");\n if (runtimeCache) return runtimeCache;\n const here = dirname(fileURLToPath(import.meta.url));\n const candidates = [join(here, \"runtime.global.js\"), join(here, \"..\", \"dist\", \"runtime.global.js\")];\n for (const c of candidates) {\n try {\n runtimeCache = await readFile(c, \"utf8\");\n return runtimeCache;\n } catch {\n /* try next */\n }\n }\n throw new PdfRenderError(\"BroadPaper runtime bundle not found. Run `pnpm --filter @broadpaper/pdf build`.\", \"RUNTIME\");\n}\n\nconst BLANK_HTML = `<!doctype html><html><head><meta charset=\"utf-8\"><title>BroadPaper</title></head><body></body></html>`;\n\n/**\n * A reusable PDF renderer bound to a Playwright browser. Each render uses a\n * fresh, isolated browser context (no cookies, storage or cache shared between\n * documents) and a strict network policy.\n */\nexport class PdfRenderer {\n constructor(private readonly browser: Browser) {}\n\n async render(opts: RenderPdfOptions): Promise<RenderPdfResult> {\n const started = Date.now();\n const timeout = opts.timeoutMs ?? 60_000;\n const runtime = await loadRuntime(opts.runtimePath);\n let context: BrowserContext | null = null;\n try {\n context = await this.browser.newContext({ javaScriptEnabled: true, offline: false, viewport: { width: 1200, height: 1600 }, deviceScaleFactor: 1, bypassCSP: false, locale: opts.locale ?? \"en-GB\", timezoneId: opts.timeZone });\n context.setDefaultTimeout(timeout);\n const counter = { count: 0 };\n const policy: NetworkPolicy = { allowedHosts: [], blockPrivateNetworks: true, maxRequests: 200, ...(opts.network ?? {}) };\n await context.route(\"**/*\", async (route) => {\n const url = route.request().url();\n const decision = await decideRequest(url, policy, counter);\n if (decision.allow) await route.continue();\n else await route.abort(\"blockedbyclient\");\n });\n\n const page = await context.newPage();\n const errors: string[] = [];\n page.on(\"pageerror\", (e) => errors.push(String(e)));\n await page.setContent(BLANK_HTML, { waitUntil: \"load\" });\n await page.addScriptTag({ content: runtime });\n if (opts.customBlocksScript) await page.addScriptTag({ content: opts.customBlocksScript });\n\n const input = {\n template: opts.template,\n data: opts.data ?? {},\n theme: opts.theme,\n dataSources: opts.dataSources ?? [],\n now: (opts.now ?? new Date()).toISOString(),\n locale: opts.locale,\n currency: opts.currency,\n timeZone: opts.timeZone,\n mode: \"preview\" as const\n };\n\n const result = (await Promise.race([\n page.evaluate(async (i) => window.BroadPaper.render(i as never), input),\n new Promise<never>((_, reject) => setTimeout(() => reject(new PdfRenderError(`Render timed out after ${timeout}ms`, \"TIMEOUT\")), timeout))\n ])) as RuntimeRenderOutput;\n\n if (errors.length) throw new PdfRenderError(`Runtime error: ${errors[0]}`, \"RUNTIME\");\n const maxPages = opts.maxPages ?? 500;\n if (result.pages > maxPages) throw new PdfRenderError(`Document has ${result.pages} pages, more than the limit of ${maxPages}`, \"TOO_MANY_PAGES\");\n\n await page.emulateMedia({ media: \"print\" });\n const pdf = await page.pdf({\n width: `${result.width}px`,\n height: `${result.height}px`,\n printBackground: true,\n preferCSSPageSize: true,\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n displayHeaderFooter: false,\n tagged: opts.tagged ?? true,\n outline: opts.outline ?? true\n });\n\n // The licence is checked here, on the way out, rather than inside the\n // page: nothing a host injects into the browser — a custom-blocks bundle,\n // its own runtime, its own CSS — sits between this and the file.\n const license = await resolveLicenseStatus(opts.license !== undefined ? { license: opts.license } : {});\n const finished = await applyMetadata(pdf, opts.metadata, opts.now, license);\n return { pdf: finished, pages: result.pages, warnings: result.warnings, durationMs: Date.now() - started };\n } catch (e) {\n if (e instanceof PdfRenderError) throw e;\n throw new PdfRenderError(`Browser failure: ${(e as Error).message}`, \"BROWSER\");\n } finally {\n await context?.close().catch(() => undefined);\n }\n }\n}\n\n/**\n * Writes document metadata (Title, Author, Subject, Keywords, Producer, dates)\n * into the PDF using pdf-lib, and stamps the evaluation mark when the licence\n * calls for one. With a fixed `now` the output is byte-stable.\n *\n * The two jobs are together because this is the last time the file is open:\n * every Chromium render ends here, so a PDF that leaves this function clean was\n * produced under a licence that says it may be.\n *\n * `license` is resolved from the configured licence when it is not supplied,\n * which keeps the guarantee for a caller reaching this function directly.\n */\nexport async function applyMetadata(pdf: Buffer, meta: PdfMetadata | undefined, now?: Date, license?: LicenseStatus): Promise<Buffer> {\n const { PDFDocument } = await import(\"pdf-lib\");\n const status = license ?? (await resolveLicenseStatus());\n const doc = await PDFDocument.load(pdf, { updateMetadata: false });\n const when = meta?.creationDate ?? now ?? new Date();\n const mark = watermarkFor(status);\n if (mark) await stampWatermark(doc, mark);\n doc.setProducer(producerString(status));\n doc.setCreator(\"BroadPaper\");\n doc.setCreationDate(when);\n doc.setModificationDate(when);\n if (meta?.title) doc.setTitle(meta.title, { showInWindowTitleBar: true });\n if (meta?.author) doc.setAuthor(meta.author);\n if (meta?.subject) doc.setSubject(meta.subject);\n if (meta?.keywords?.length) doc.setKeywords(meta.keywords);\n const bytes = await doc.save({ useObjectStreams: true, addDefaultPage: false });\n return Buffer.from(bytes);\n}\n\nexport interface BrowserFactory {\n launch(): Promise<Browser>;\n}\n\n/**\n * Convenience: renders one PDF with a temporary browser. For servers use\n * `PdfRenderer` with a long-lived browser instead.\n */\nexport async function renderPdf(opts: RenderPdfOptions & { browser?: Browser; launch?: () => Promise<Browser> }): Promise<RenderPdfResult> {\n let browser = opts.browser;\n let own = false;\n if (!browser) {\n const launch = opts.launch ?? defaultLaunch;\n browser = await launch();\n own = true;\n }\n try {\n return await new PdfRenderer(browser).render(opts);\n } finally {\n if (own) await browser.close().catch(() => undefined);\n }\n}\n\nexport async function defaultLaunch(): Promise<Browser> {\n // Playwright is an optional peer dependency: this package is the fidelity\n // reference rather than the recommended backend, and most hosts render with\n // Forme and never launch a browser at all. Neither driver being installed is\n // therefore an ordinary configuration and not a broken install, so it has to\n // say so — the bare module resolution error names a package the host never\n // knowingly asked for.\n let mod: typeof import(\"playwright-core\");\n try {\n mod = (await import(\"playwright\").catch(() => import(\"playwright-core\"))) as typeof import(\"playwright-core\");\n } catch {\n throw new PdfRenderError(\n \"The Chromium backend needs Playwright, an optional peer dependency of @broadpaper/pdf. Install playwright (or playwright-core, if you supply your own browser), or render with @broadpaper/forme, which needs no browser at all.\",\n \"BROWSER\"\n );\n }\n return mod.chromium.launch({ headless: true, args: [\"--disable-gpu\", \"--font-render-hinting=none\", \"--disable-dev-shm-usage\"] });\n}\n","/**\n * The evaluation mark, drawn into a finished PDF.\n *\n * The browserless backend hands the engine a watermark node and lets it draw;\n * Chromium has no such notion, so the mark goes on afterwards, into the file.\n * That is deliberately the *last* thing that happens to a PDF here rather than\n * a stylesheet injected into the page: a host supplying its own custom-blocks\n * bundle, its own CSS or its own runtime can change what the page looks like,\n * and none of it can change what comes out of this function.\n *\n * One line per page, centred, rotated, at the same colour and opacity the\n * engine uses, so an evaluation PDF looks the same whichever backend produced\n * it.\n */\nimport type { PDFDocument } from \"pdf-lib\";\nimport type { WatermarkSpec } from \"@broadpaper/license\";\n\nexport async function stampWatermark(doc: PDFDocument, spec: WatermarkSpec): Promise<void> {\n const { StandardFonts, degrees, rgb } = await import(\"pdf-lib\");\n // Helvetica-Bold is one of the fourteen faces every PDF reader has, so the\n // mark needs no embedded font and adds nothing to the file size.\n const font = await doc.embedFont(StandardFonts.HelveticaBold);\n const color = hexToRgb(spec.color);\n const radians = (spec.angle * Math.PI) / 180;\n const width = font.widthOfTextAtSize(spec.text, spec.fontSize);\n const height = font.heightAtSize(spec.fontSize);\n\n for (const page of doc.getPages()) {\n const { width: pw, height: ph } = page.getSize();\n // drawText places the baseline at (x, y) and then rotates about that point,\n // so the centring has to be done in the rotated frame: walk back along the\n // text's own axis by half its length, and off it by half its height.\n const x = pw / 2 - (Math.cos(radians) * width) / 2 + (Math.sin(radians) * height) / 2;\n const y = ph / 2 - (Math.sin(radians) * width) / 2 - (Math.cos(radians) * height) / 2;\n page.drawText(spec.text, {\n x,\n y,\n size: spec.fontSize,\n font,\n color: rgb(color.r, color.g, color.b),\n opacity: spec.opacity,\n rotate: degrees(spec.angle)\n });\n }\n}\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());\n /* c8 ignore next -- the spec's colour is a constant; this guards a host that edited it */\n if (!m) return { r: 0.78, g: 0.06, b: 0.18 };\n const n = parseInt(m[1]!, 16);\n return { r: ((n >> 16) & 255) / 255, g: ((n >> 8) & 255) / 255, b: (n & 255) / 255 };\n}\n","import { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport type { Browser } from \"playwright-core\";\nimport { PdfRenderer, PdfRenderError, defaultLaunch, type RenderPdfOptions } from \"./render-pdf.js\";\nimport type { NetworkPolicy } from \"./ssrf.js\";\n\nexport interface PdfServerOptions {\n port?: number;\n host?: string;\n /** Shared-secret bearer token. Strongly recommended outside of local development. */\n token?: string;\n /** Maximum request body size in bytes. Default 25 MB. */\n maxBodyBytes?: number;\n /** Concurrent renders. Default 4. */\n concurrency?: number;\n /** Default network policy (request body may narrow but never widen it). */\n network?: NetworkPolicy;\n /** Custom blocks bundle (JS source) injected into every render. */\n customBlocksScript?: string;\n launch?: () => Promise<Browser>;\n timeoutMs?: number;\n maxPages?: number;\n log?: (msg: string) => void;\n}\n\nexport interface PdfServer {\n server: Server;\n port: number;\n close(): Promise<void>;\n}\n\ninterface RenderRequestBody extends Omit<RenderPdfOptions, \"now\" | \"network\" | \"customBlocksScript\" | \"runtimePath\" | \"metadata\"> {\n now?: string;\n network?: { allowedHosts?: string[] };\n metadata?: { title?: string; author?: string; subject?: string; keywords?: string[] };\n /** \"pdf\" (default) returns application/pdf; \"json\" returns { pdfBase64, pages, warnings }. */\n format?: \"pdf\" | \"json\";\n}\n\nfunction readJson(req: IncomingMessage, limit: number): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on(\"data\", (c: Buffer) => {\n size += c.length;\n if (size > limit) {\n reject(new Error(\"Request body too large\"));\n req.destroy();\n return;\n }\n chunks.push(c);\n });\n req.on(\"end\", () => {\n try {\n resolve(JSON.parse(Buffer.concat(chunks).toString(\"utf8\")));\n } catch {\n reject(new Error(\"Invalid JSON\"));\n }\n });\n req.on(\"error\", reject);\n });\n}\n\nfunction send(res: ServerResponse, status: number, body: unknown, headers: Record<string, string> = {}) {\n const json = JSON.stringify(body);\n res.writeHead(status, { \"content-type\": \"application/json; charset=utf-8\", \"content-length\": Buffer.byteLength(json), ...headers });\n res.end(json);\n}\n\n/**\n * Starts a small, dependency-free HTTP service:\n * POST /render → PDF bytes (or JSON with format: \"json\")\n * GET /health → { ok, browser }\n *\n * Deploy it next to your application. Report data never leaves your network.\n */\nexport async function createPdfServer(opts: PdfServerOptions = {}): Promise<PdfServer> {\n const log = opts.log ?? (() => undefined);\n const browser = await (opts.launch ?? defaultLaunch)();\n const renderer = new PdfRenderer(browser);\n const concurrency = opts.concurrency ?? 4;\n let active = 0;\n const queue: Array<() => void> = [];\n const acquire = () =>\n new Promise<void>((resolve) => {\n if (active < concurrency) {\n active++;\n resolve();\n } else queue.push(resolve);\n });\n const release = () => {\n active--;\n const next = queue.shift();\n if (next) {\n active++;\n next();\n }\n };\n\n const server = createServer(async (req, res) => {\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n res.setHeader(\"x-content-type-options\", \"nosniff\");\n if (req.method === \"GET\" && url.pathname === \"/health\") return send(res, 200, { ok: true, browser: browser.isConnected(), active, queued: queue.length });\n if (req.method === \"OPTIONS\") {\n res.writeHead(204, { \"access-control-allow-origin\": \"*\", \"access-control-allow-headers\": \"authorization, content-type\", \"access-control-allow-methods\": \"POST, GET, OPTIONS\" });\n return res.end();\n }\n if (req.method !== \"POST\" || url.pathname !== \"/render\") return send(res, 404, { error: \"Not found\" });\n if (opts.token) {\n const auth = req.headers.authorization ?? \"\";\n if (auth !== `Bearer ${opts.token}`) return send(res, 401, { error: \"Unauthorised\" });\n }\n let body: RenderRequestBody;\n try {\n body = (await readJson(req, opts.maxBodyBytes ?? 25 * 1024 * 1024)) as RenderRequestBody;\n } catch (e) {\n return send(res, 400, { error: (e as Error).message });\n }\n if (!body || typeof body !== \"object\" || !body.template) return send(res, 400, { error: \"Missing template\" });\n\n // Narrow the network policy: request may only restrict, never widen.\n const serverHosts = opts.network?.allowedHosts ?? [];\n const requested = body.network?.allowedHosts;\n const allowedHosts = requested ? requested.filter((h) => serverHosts.includes(\"*\") || serverHosts.includes(h)) : serverHosts;\n\n await acquire();\n const started = Date.now();\n try {\n const result = await renderer.render({\n template: body.template,\n data: body.data,\n theme: body.theme,\n dataSources: body.dataSources,\n now: body.now ? new Date(body.now) : undefined,\n locale: body.locale,\n currency: body.currency,\n timeZone: body.timeZone,\n metadata: body.metadata,\n network: { ...(opts.network ?? {}), allowedHosts },\n customBlocksScript: opts.customBlocksScript,\n timeoutMs: opts.timeoutMs,\n maxPages: opts.maxPages\n });\n log(`render ok pages=${result.pages} ms=${result.durationMs}`);\n res.setHeader(\"access-control-allow-origin\", \"*\");\n if (body.format === \"json\") return send(res, 200, { pdfBase64: result.pdf.toString(\"base64\"), pages: result.pages, warnings: result.warnings, durationMs: result.durationMs });\n res.writeHead(200, { \"content-type\": \"application/pdf\", \"content-length\": result.pdf.length, \"x-broadpaper-pages\": String(result.pages), \"x-broadpaper-warnings\": String(result.warnings.length), \"content-disposition\": `inline; filename=\"${(body.metadata?.title ?? \"report\").replace(/[^\\w.-]+/g, \"_\")}.pdf\"` });\n res.end(result.pdf);\n } catch (e) {\n const err = e as PdfRenderError;\n log(`render failed ${err.code ?? \"\"} ${err.message} ms=${Date.now() - started}`);\n const status = err instanceof PdfRenderError ? (err.code === \"TIMEOUT\" ? 504 : err.code === \"TOO_MANY_PAGES\" ? 413 : 500) : 500;\n res.setHeader(\"access-control-allow-origin\", \"*\");\n send(res, status, { error: err.message, code: err.code ?? \"UNKNOWN\" });\n } finally {\n release();\n }\n });\n\n const port = opts.port ?? 4780;\n await new Promise<void>((resolve) => server.listen(port, opts.host ?? \"0.0.0.0\", resolve));\n const address = server.address();\n const actualPort = typeof address === \"object\" && address ? address.port : port;\n log(`BroadPaper PDF service listening on http://${opts.host ?? \"0.0.0.0\"}:${actualPort}`);\n return {\n server,\n port: actualPort,\n close: async () => {\n await new Promise<void>((resolve) => server.close(() => resolve()));\n await browser.close().catch(() => undefined);\n }\n };\n}\n"],"mappings":"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","names":["i","G","mod"]}
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  createPdfServer
4
- } from "./chunk-4YSTS7DA.js";
4
+ } from "./chunk-PFCVDSUU.js";
5
5
 
6
6
  // src/cli.ts
7
7
  var env = process.env;
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Browser } from 'playwright-core';
2
2
  import { ReportTemplate, ReportData, Theme, DataSource, BlockDefinition, defineBlock, h } from '@broadpaper/core';
3
3
  import { LicenseStatus } from '@broadpaper/license';
4
- export { BroadPaper, BroadPaperConfig, Entitlement, LicensePayload, LicenseState, LicenseStatus, configure, parseLicense, resolveLicenseStatus, verifyLicense } from '@broadpaper/license';
4
+ export { BroadPaper, BroadPaperConfig, LicensePayload, LicenseState, LicenseStatus, LicenseType, Plan, configure, parseLicense, resolveLicenseStatus, verifyLicense } from '@broadpaper/license';
5
5
  import { Server } from 'node:http';
6
6
 
7
7
  interface NetworkPolicy {
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  renderPdf,
14
14
  resolveLicenseStatus,
15
15
  verifyLicense
16
- } from "./chunk-4YSTS7DA.js";
16
+ } from "./chunk-PFCVDSUU.js";
17
17
  export {
18
18
  BroadPaper,
19
19
  PdfRenderError,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@broadpaper/pdf",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "BroadPaper PDF renderer: headless Chromium printing of the paged document, with an HTTP server, SSRF guard and a browser print fallback.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -28,10 +28,10 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "pdf-lib": "^1.17.1",
31
- "@broadpaper/core": "0.1.1",
32
- "@broadpaper/blocks": "0.1.1",
33
- "@broadpaper/license": "0.1.1",
34
- "@broadpaper/renderer": "0.1.1"
31
+ "@broadpaper/core": "0.2.0",
32
+ "@broadpaper/blocks": "0.2.0",
33
+ "@broadpaper/renderer": "0.2.0",
34
+ "@broadpaper/license": "0.2.0"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "playwright": ">=1.40",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../license/src/encoding.ts","../../license/src/format.ts","../../../node_modules/.pnpm/@noble+ed25519@3.2.0/node_modules/@noble/ed25519/index.js","../../license/src/trusted-keys.ts","../../license/src/types.ts","../../license/src/verify.ts","../../license/src/config.ts","../../license/src/watermark.ts","../src/server/ssrf.ts","../src/server/render-pdf.ts","../src/server/watermark.ts","../src/server/http.ts"],"sourcesContent":["/**\n * base64url and UTF-8, without depending on Node or on the DOM.\n *\n * The SDK runs in Node, in edge runtimes, in a worker and in a browser, and the\n * licence string has to decode identically in all four. `atob`/`btoa` exist\n * everywhere modern but are byte-oriented and mangle anything above U+00FF, so\n * text goes through `TextEncoder`/`TextDecoder` first and only bytes are\n * base64'd. The tables below are the whole implementation, which is smaller\n * than the runtime detection needed to use `Buffer` where it happens to exist.\n */\n\nconst ALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\nconst LOOKUP = /* @__PURE__ */ (() => {\n const t = new Int8Array(128).fill(-1);\n for (let i = 0; i < ALPHABET.length; i++) t[ALPHABET.charCodeAt(i)] = i;\n // Accept standard base64 as well, so a licence that survived a round trip\n // through a system that rewrote the alphabet still reads.\n t[\"+\".charCodeAt(0)] = 62;\n t[\"/\".charCodeAt(0)] = 63;\n return t;\n})();\n\nexport function bytesToBase64Url(bytes: Uint8Array): string {\n let out = \"\";\n let i = 0;\n for (; i + 2 < bytes.length; i += 3) {\n const n = (bytes[i]! << 16) | (bytes[i + 1]! << 8) | bytes[i + 2]!;\n out += ALPHABET[(n >>> 18) & 63]! + ALPHABET[(n >>> 12) & 63]! + ALPHABET[(n >>> 6) & 63]! + ALPHABET[n & 63]!;\n }\n const rest = bytes.length - i;\n if (rest === 1) {\n const n = bytes[i]! << 16;\n out += ALPHABET[(n >>> 18) & 63]! + ALPHABET[(n >>> 12) & 63]!;\n } else if (rest === 2) {\n const n = (bytes[i]! << 16) | (bytes[i + 1]! << 8);\n out += ALPHABET[(n >>> 18) & 63]! + ALPHABET[(n >>> 12) & 63]! + ALPHABET[(n >>> 6) & 63]!;\n }\n return out;\n}\n\n/** Throws on anything that is not base64/base64url. Padding is optional. */\nexport function base64UrlToBytes(text: string): Uint8Array {\n let end = text.length;\n while (end > 0 && text[end - 1] === \"=\") end--;\n const chars: number[] = [];\n for (let i = 0; i < end; i++) {\n const code = text.charCodeAt(i);\n const value = code < 128 ? LOOKUP[code]! : -1;\n if (value < 0) throw new Error(`not base64: ${JSON.stringify(text[i])} at ${i}`);\n chars.push(value);\n }\n // 4 base64 characters carry 3 bytes; a group of 1 is never valid.\n if (chars.length % 4 === 1) throw new Error(\"not base64: truncated\");\n const out = new Uint8Array(Math.floor((chars.length * 3) / 4));\n let o = 0;\n let i = 0;\n for (; i + 3 < chars.length; i += 4) {\n const n = (chars[i]! << 18) | (chars[i + 1]! << 12) | (chars[i + 2]! << 6) | chars[i + 3]!;\n out[o++] = (n >>> 16) & 255;\n out[o++] = (n >>> 8) & 255;\n out[o++] = n & 255;\n }\n const rest = chars.length - i;\n if (rest === 2) {\n out[o++] = ((chars[i]! << 18) | (chars[i + 1]! << 12)) >>> 16;\n } else if (rest === 3) {\n const n = (chars[i]! << 18) | (chars[i + 1]! << 12) | (chars[i + 2]! << 6);\n out[o++] = (n >>> 16) & 255;\n out[o++] = (n >>> 8) & 255;\n }\n return out;\n}\n\nconst encoder = /* @__PURE__ */ new TextEncoder();\nconst decoder = /* @__PURE__ */ new TextDecoder(\"utf-8\", { fatal: true });\n\nexport const utf8ToBytes = (text: string): Uint8Array => encoder.encode(text);\nexport const bytesToUtf8 = (bytes: Uint8Array): string => decoder.decode(bytes);\n","/**\n * The licence string.\n *\n * BP1.<base64url payload>.<base64url signature>\n *\n * Three parts, dot-separated, safe in an environment variable, a YAML file, a\n * URL and a shell argument without quoting. The leading `BP1` is the *string\n * format* version and `payload.version` is the *payload schema* version; they\n * move independently, and both are checked, so a licence issued for a later\n * format is reported as unsupported rather than as corrupt.\n *\n * What is signed is the bytes of `BP1.<payload>` — prefix included. Signing the\n * encoded text rather than the decoded object means verification never depends\n * on two JSON serialisers agreeing about key order or number formatting, and\n * covering the prefix stops a payload being lifted into a future format that\n * might read a field differently.\n */\nimport { base64UrlToBytes, bytesToBase64Url, bytesToUtf8, utf8ToBytes } from \"./encoding.js\";\nimport { PRODUCT, type Entitlement, type LicensePayload } from \"./types.js\";\n\n/** The only string format this SDK can read. */\nexport const FORMAT_PREFIX = \"BP1\";\n\n/** A licence string split into its parts, before any signature check. */\nexport interface ParsedLicense {\n prefix: string;\n /** The exact text that was signed. */\n signedText: string;\n encodedPayload: string;\n signature: Uint8Array;\n payload: LicensePayload;\n}\n\nexport class LicenseFormatError extends Error {\n constructor(\n message: string,\n /** `unsupported` when the licence is well-formed but newer than this SDK. */\n readonly kind: \"invalid\" | \"unsupported\" = \"invalid\"\n ) {\n super(message);\n this.name = \"LicenseFormatError\";\n }\n}\n\nconst ENTITLEMENTS: readonly Entitlement[] = [\"internal\", \"saas\"];\n\n/** Whitespace is stripped: licences get pasted, wrapped and indented. */\nexport function normalizeLicense(license: string): string {\n return license.replace(/\\s+/g, \"\");\n}\n\n/**\n * Reads a licence string without verifying it.\n *\n * Nothing here decides whether a licence is *honoured* — that needs the\n * signature — but a structurally broken string can be rejected before any\n * cryptography happens, and the account UI can display a licence's contents\n * without holding a public key.\n */\nexport function parseLicense(license: string): ParsedLicense {\n const text = normalizeLicense(license);\n if (!text) throw new LicenseFormatError(\"the licence string is empty\");\n\n const parts = text.split(\".\");\n if (parts.length !== 3) throw new LicenseFormatError(`expected three dot-separated parts, found ${parts.length}`);\n const [prefix, encodedPayload, encodedSignature] = parts as [string, string, string];\n\n if (prefix !== FORMAT_PREFIX) {\n // A licence issued in a format this SDK predates is a version problem, not\n // a corrupt string, and the fix is to upgrade rather than to re-copy it.\n const known = /^BP\\d+$/.test(prefix);\n throw new LicenseFormatError(\n known\n ? `licence format ${prefix} is newer than this version of BroadPaper, which reads ${FORMAT_PREFIX}`\n : `unrecognised licence prefix ${JSON.stringify(prefix)}`,\n known ? \"unsupported\" : \"invalid\"\n );\n }\n if (!encodedPayload || !encodedSignature) throw new LicenseFormatError(\"the licence string has an empty part\");\n\n let json: string;\n let signature: Uint8Array;\n try {\n json = bytesToUtf8(base64UrlToBytes(encodedPayload));\n signature = base64UrlToBytes(encodedSignature);\n } catch (e) {\n throw new LicenseFormatError(`the licence string is not valid base64 (${(e as Error).message})`);\n }\n if (signature.length !== 64) throw new LicenseFormatError(`an Ed25519 signature is 64 bytes, this one is ${signature.length}`);\n\n let raw: unknown;\n try {\n raw = JSON.parse(json);\n } catch {\n throw new LicenseFormatError(\"the licence payload is not valid JSON\");\n }\n\n return {\n prefix,\n signedText: `${prefix}.${encodedPayload}`,\n encodedPayload,\n signature,\n payload: readPayload(raw)\n };\n}\n\n/**\n * Validates the payload's shape.\n *\n * Unknown properties are kept, not rejected: they are inside the signature, so\n * a licence issued by a later BroadPaper carrying a field this SDK has never\n * heard of is still a licence this SDK can honour.\n */\nfunction readPayload(raw: unknown): LicensePayload {\n if (typeof raw !== \"object\" || raw === null || Array.isArray(raw)) throw new LicenseFormatError(\"the licence payload is not an object\");\n const o = raw as Record<string, unknown>;\n\n const version = o.version;\n if (version !== 1) {\n const numeric = typeof version === \"number\" && Number.isInteger(version) && version > 1;\n throw new LicenseFormatError(\n numeric ? `licence payload version ${version} is newer than this version of BroadPaper, which reads version 1` : \"the licence payload has no usable version\",\n numeric ? \"unsupported\" : \"invalid\"\n );\n }\n\n const text = (key: string): string => {\n const value = o[key];\n if (typeof value !== \"string\" || value === \"\") throw new LicenseFormatError(`the licence payload is missing ${key}`);\n return value;\n };\n const seconds = (key: string): number => {\n const value = o[key];\n if (typeof value !== \"number\" || !Number.isFinite(value)) throw new LicenseFormatError(`the licence payload is missing ${key}`);\n return value;\n };\n\n const entitlement = text(\"entitlement\");\n if (!ENTITLEMENTS.includes(entitlement as Entitlement)) {\n // An entitlement this SDK does not know is a newer commercial model, and\n // refusing to honour a licence we cannot classify would punish the customer\n // for buying something new. It is reported as unsupported so the developer\n // is told to upgrade.\n throw new LicenseFormatError(`this version of BroadPaper does not know the entitlement ${JSON.stringify(entitlement)}`, \"unsupported\");\n }\n\n return {\n ...o,\n version: 1,\n keyId: text(\"keyId\"),\n licenseId: text(\"licenseId\"),\n customerId: text(\"customerId\"),\n customerName: text(\"customerName\"),\n product: text(\"product\") as typeof PRODUCT,\n entitlement: entitlement as Entitlement,\n issuedAt: seconds(\"issuedAt\"),\n expiresAt: seconds(\"expiresAt\")\n };\n}\n\n/**\n * Encodes a payload into the text that gets signed.\n *\n * Exported because BroadPaper's own licence issuer must produce byte-identical\n * input to what the SDK verifies, and the only way to guarantee that is for\n * both to call this function.\n */\nexport function encodeSigningInput(payload: LicensePayload): { signedText: string; encodedPayload: string } {\n const encodedPayload = bytesToBase64Url(utf8ToBytes(JSON.stringify(payload)));\n return { encodedPayload, signedText: `${FORMAT_PREFIX}.${encodedPayload}` };\n}\n\n/** Assembles the final licence string from a payload and its signature. */\nexport function formatLicense(payload: LicensePayload, signature: Uint8Array): string {\n if (signature.length !== 64) throw new LicenseFormatError(`an Ed25519 signature is 64 bytes, this one is ${signature.length}`);\n const { encodedPayload } = encodeSigningInput(payload);\n return `${FORMAT_PREFIX}.${encodedPayload}.${bytesToBase64Url(signature)}`;\n}\n","/*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) */\n/**\n * 5KB JS implementation of ed25519 EdDSA signatures.\n * Targets RFC8032, FIPS 186-5, and ZIP215 behavior.\n * @module\n * @example\n * ```js\nimport * as ed from '@noble/ed25519';\n(async () => {\n const secretKey = ed.utils.randomSecretKey();\n const message = Uint8Array.from([0xab, 0xbc, 0xcd, 0xde]);\n const pubKey = await ed.getPublicKeyAsync(secretKey); // Sync methods are also present\n const signature = await ed.signAsync(message, secretKey);\n const isValid = await ed.verifyAsync(signature, message, pubKey);\n})();\n```\n */\n/**\n * Curve params. edwards25519 uses the RFC equation `-x² + y² = 1 + dx²y²`.\n * The stored `a` literal below is `p - 1`, i.e. the field-element encoding of RFC `a = -1`.\n * * P = `2n**255n - 19n` // field over which calculations are done\n * * N = `2n**252n + 27742317777372353535851937790883648493n` // prime-order subgroup order\n * * h = 8 // cofactor\n * * a = `Fp.create(BigInt(-1))` // equation param, stored here as `p - 1`\n * * d = -121665/121666 a.k.a. `Fp.neg(121665 * Fp.inv(121666))` // equation param\n * * Gx, Gy are coordinates of Generator / base point\n *\n * Mirror noble-curves: Point.CURVE() exposes shared params, but callers must not be able to mutate\n * that shared view and desynchronize it from the arithmetic constants captured below.\n */\nconst freeze = Object.freeze;\nconst P = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn;\nconst N = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3edn;\nconst _d = 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3n;\nconst Gx = 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51an;\nconst Gy = 0x6666666666666666666666666666666666666666666666666666666666666658n;\nconst _a = P - 1n; // field-element encoding of RFC `a = -1`\nconst ed25519_CURVE = freeze({\n p: P,\n n: N,\n h: 8n,\n a: _a,\n d: _d,\n Gx,\n Gy,\n});\n// Shared 32-byte encoded width for Ed25519 points, scalars, signatures/2, and keys. Named LEN\n// rather than RFC 8032's `L`, which names the group order (stored here as `N`).\nconst LEN = 32;\n// Helpers and Precomputes sections are reused between libraries\n// ## Helpers\n// ----------\n/** Checks if something is Uint8Array. Be careful: nodejs Buffer will return true. */\nconst isBytes = (a) => {\n // Plain `instanceof Uint8Array` is too strict for some Buffer / proxy / cross-realm cases.\n // The fallback still requires a real ArrayBuffer view, so plain\n // JSON-deserialized `{ constructor: ... }` spoofing is rejected, and\n // `BYTES_PER_ELEMENT === 1` keeps the fallback on byte-oriented views.\n return (a instanceof Uint8Array ||\n (ArrayBuffer.isView(a) &&\n a.constructor.name === 'Uint8Array' &&\n a.BYTES_PER_ELEMENT === 1));\n};\n/** Asserts something is Bytes. */\nconst abytes = (value, length, title = '') => {\n // Success path first: this runs at the start of every update() / digestInto(), and the\n // common `abytes(data)` form must not pay for length handling it does not use.\n if (isBytes(value) && (length === undefined || value.length === length))\n return value;\n // Error path: recompute freely to build the exact message.\n const bytes = isBytes(value);\n const ofLen = length !== undefined ? ` of length ${length}` : '';\n const got = bytes ? `length=${value.length}` : `type=${typeof value}`;\n const message = (title ? `\"${title}\" ` : '') + 'expected Uint8Array' + ofLen + ', got ' + got;\n if (!bytes)\n throw new TypeError(message);\n throw new RangeError(message);\n};\n// Validate, then take one owned copy, so later caller mutation cannot be observed — e.g. cannot\n// make sign()'s nonce derivation and challenge derivation see different messages.\nconst snapshotBytes = (value, title = '', length) => Uint8Array.from(abytes(value, length, title));\n// Callers keep values non-negative and within the requested width; padStart() won't truncate over-wide inputs.\nconst padh = (n, pad) => n.toString(16).padStart(pad, '0');\n/** Convert byte array to hex string. */\nconst bytesToHex = (bytes) => {\n let hex = '';\n for (const byte of abytes(bytes))\n hex += padh(byte, 2);\n return hex;\n};\n/** Convert hex string to byte array. */\nconst hexToBytes = (hex) => {\n const e = 'hex invalid'; // Strict ASCII hex only, with one generic error for parse failures.\n if (typeof hex !== 'string')\n throw new TypeError(e);\n if (hex.length % 2 || !/^[\\da-f]*$/i.test(hex))\n throw new RangeError(e);\n const array = new Uint8Array(hex.length / 2);\n for (let ai = 0, hi = 0; ai < array.length; ai++, hi += 2) {\n const n1 = hex.charCodeAt(hi);\n const n2 = hex.charCodeAt(hi + 1);\n // Regex guarantees ASCII. For 0..9/A..F/a..f, this maps char codes to 0..15.\n array[ai] = ((n1 & 15) + (n1 >> 6) * 9) * 16 + (n2 & 15) + (n2 >> 6) * 9;\n }\n return array;\n};\n// WebCrypto is available in all modern environments\n/** Copies several Uint8Arrays into one. */\nconst concatBytes = (...arrays) => {\n let sum = 0;\n for (const a of arrays)\n sum += abytes(a).length;\n const res = new Uint8Array(sum);\n let pad = 0;\n for (const a of arrays) {\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n};\n/**\n * WebCrypto OS-level CSPRNG (random number generator).\n * Will throw when not available; large-request ceilings are delegated to getRandomValues().\n */\nconst randomBytes = (len = LEN) => {\n const c = globalThis?.crypto;\n if (typeof c?.getRandomValues !== 'function')\n throw new Error('crypto.getRandomValues must be defined, consider polyfill');\n return c.getRandomValues(new Uint8Array(len));\n};\n/** Inclusive-lower, exclusive-upper bigint range assertion. */\nconst arange = (n, min, max, msg = 'bad number: out of range') => {\n if (typeof n !== 'bigint')\n throw new TypeError(msg);\n if (min <= n && n < max)\n return n;\n throw new RangeError(msg);\n};\n/** Canonical modular reduction. Callers must provide a positive modulus. */\nconst mod = (a, b = P) => ((a %= b) >= 0n ? a : b + a);\n// Low-255-bit mask used by the `2^255 - 19` fast reduction in `modP(...)`.\nconst P_MASK = (1n << 255n) - 1n;\n// Fast reduction for the special prime `2^255 - 19`. This path assumes nonnegative inputs; the\n// generic fallback would simply be `mod(num, P)`.\nconst modP = (num) => {\n if (num < 0n)\n throw new RangeError('negative coordinate');\n let r = (num >> 255n) * 19n + (num & P_MASK);\n r = (r >> 255n) * 19n + (r & P_MASK);\n return r % P;\n};\n// Reduce modulo the subgroup order stored in implementation constant `N` (RFC 8032's `L`).\nconst modN = (a) => mod(a, N);\n/** Modular inversion using extended euclidean GCD. Variable-time (non-CT). */\nconst invert = (number, modulo) => {\n if (number === 0n)\n throw new Error('invert: expected non-zero number');\n // modulo = 1 is the zero ring: gcd(x, 1) = 1 makes the loop below \"succeed\" and return the\n // useless inverse 0. Reject it like pow() and invertCt() do.\n if (modulo <= 1n)\n throw new Error('invert: expected modulus > 1, got ' + modulo);\n // This is variable-time: the loop count depends on `number`.\n let a = mod(number, modulo);\n let b = modulo;\n // Only the Bézout coefficient of `number` (x/u chain) is tracked; the coefficient of `modulo`\n // never affects the output, so it is not computed.\n // prettier-ignore\n let x = 0n, u = 1n;\n while (a !== 0n) {\n const q = b / a;\n const r = b - a * q;\n const m = x - u * q;\n // prettier-ignore\n b = a, a = r, x = u, u = m;\n }\n const gcd = b;\n if (gcd !== 1n)\n throw new Error('invert: does not exist');\n return mod(x, modulo);\n};\n// Dynamic lookup keeps sync/async hash providers configurable at runtime. Both exported slots are\n// caller-owned and may be unset; wrapper helpers use this lookup first and then enforce the digest\n// contract instead of trusting provider output.\nconst _hash = (name) => {\n // @ts-ignore\n const fn = hashes[name];\n if (typeof fn !== 'function')\n throw new Error('hashes.' + name + ' not set');\n return fn;\n};\n// All exported provider slots are caller-configurable and may be unset or return arbitrary values,\n// so wrapper helpers must enforce the exact 64-byte SHA-512 digest contract instead of trusting providers.\nconst callHash = (name, ...m) => abytes(_hash(name)(concatBytes(...m)), 64, 'digest');\nconst callHashAsync = async (name, ...m) => abytes(await _hash(name)(concatBytes(...m)), 64, 'digest');\n/**\n * SHA-512 helper used by the synchronous API.\n * @param msg - Message bytes to hash.\n * @returns 64-byte SHA-512 digest.\n * @example\n * Hash message bytes after wiring the synchronous SHA-512 implementation.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const digest = ed.hash(new Uint8Array([1, 2, 3]));\n * ```\n */\n// Public helper validates the message boundary explicitly; the configured provider is still looked\n// up dynamically and its output is checked with `callHash(...)`.\nconst hash = (msg) => callHash('sha512', abytes(msg, undefined, 'message'));\n// Runtime class guard: this is `instanceof Point`, so cross-realm / duplicate-bundle Point objects\n// are rejected even if they are structurally identical.\nconst apoint = (p) => {\n if (p instanceof Point)\n return p;\n throw new TypeError('Point expected');\n};\n// ## End of Helpers\n// -----------------\n// Exclusive upper bound `2^256` used by 32-byte decode/serialization range checks.\nconst B256 = 2n ** 256n;\n/**\n * Point in XYZT extended coordinates.\n * @param X - X coordinate.\n * @param Y - Y coordinate.\n * @param Z - Projective Z coordinate.\n * @param T - Cached cross-product term.\n * @example\n * Do point arithmetic with the built-in base point and encode the result as hex.\n *\n * ```ts\n * const hex = Point.BASE.double().toHex();\n * ```\n */\nclass Point {\n static BASE;\n static ZERO;\n X;\n Y;\n Z;\n T;\n // Constructor only bounds-checks and freezes XYZT coordinates; it does not prove the point is\n // on-curve or that T matches X*Y/Z.\n constructor(X, Y, Z, T) {\n const max = B256;\n this.X = arange(X, 0n, max);\n this.Y = arange(Y, 0n, max);\n this.Z = arange(Z, 1n, max);\n this.T = arange(T, 0n, max);\n freeze(this);\n }\n static CURVE() {\n return ed25519_CURVE;\n }\n static fromAffine(p) {\n return new Point(p.x, p.y, 1n, modP(p.x * p.y));\n }\n /** RFC8032 5.1.3: Uint8Array to Point. */\n static fromBytes(bytes, zip215 = false) {\n const normed = snapshotBytes(bytes, 'point', LEN); // owned copy: sign-bit mask below mutates it\n // adjust first LE byte = last BE byte\n const lastByte = normed[31];\n normed[31] = lastByte & ~0x80;\n const y = bytesToNumberLE(normed);\n // After clearing the sign bit, parsed `y` is always < 2^255. ZIP-215 still accepts the full\n // post-mask range here, while strict RFC8032 decoding further requires `y < p`.\n if (!zip215)\n arange(y, 0n, P);\n const y2 = modP(y * y); // y²\n const u = mod(y2 - 1n); // u=y²-1\n const v = modP(_d * y2 + 1n); // v=dy²+1\n let { isValid, value: x } = uvRatio(u, v); // (uv³)(uv⁷)^(p-5)/8; square root\n if (!isValid)\n throw new Error('bad point: y not sqrt'); // not square root: bad point\n const isLastByteOdd = !!(lastByte & 0x80); // x_0, last bit\n // ZIP-215-compatible decoding keeps the x=0 / sign-bit=1 encoding accepted; strict RFC 8032\n // rejects it, but the vendored ZIP-215 compliance vectors include this form in A/R bytes.\n if (!zip215 && x === 0n && isLastByteOdd)\n throw new Error('bad point: x==0, isLastByteOdd'); // x=0, x_0=1\n if (isLastByteOdd !== !!(x & 1n))\n x = mod(-x); // adjust sign of x coordinate\n return new Point(x, y, 1n, modP(x * y)); // Z=1, T=xy\n }\n static fromHex(hex, zip215) {\n return Point.fromBytes(hexToBytes(hex), zip215);\n }\n get x() {\n return this.toAffine().x;\n }\n get y() {\n return this.toAffine().y;\n }\n /** Checks if the point is valid and on-curve. */\n assertValidity() {\n const a = _a;\n const d = _d;\n const p = this;\n // Intentional stricter-than-on-curve policy: reject ZERO by default because many protocols\n // require a non-zero point, and silently accepting identity points is a common caller mistake.\n if (p.is0())\n throw new Error('bad point: ZERO');\n // Equation in affine coordinates: ax² + y² = 1 + dx²y²\n // Equation in projective coordinates (X/Z, Y/Z, Z): (aX² + Y²)Z² = Z⁴ + dX²Y²\n const { X, Y, Z, T } = p;\n const X2 = modP(X * X); // X²\n const Y2 = modP(Y * Y); // Y²\n const Z2 = modP(Z * Z); // Z²\n const Z4 = modP(Z2 * Z2); // Z⁴\n const aX2 = modP(X2 * a); // aX²\n const left = modP(Z2 * (aX2 + Y2)); // (aX² + Y²)Z²\n const right = mod(Z4 + modP(d * modP(X2 * Y2))); // Z⁴ + dX²Y²\n if (left !== right)\n throw new Error('bad point: equation left != right (1)');\n // In Extended coordinates we also have T, which is x*y=T/Z: check X*Y == Z*T\n const XY = modP(X * Y);\n const ZT = modP(Z * T);\n if (XY !== ZT)\n throw new Error('bad point: equation left != right (2)');\n return this;\n }\n /** Equality check: compare points P&Q. */\n equals(other) {\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const { X: X2, Y: Y2, Z: Z2 } = apoint(other); // checks class equality\n return modP(X1 * Z2) === modP(X2 * Z1) && modP(Y1 * Z2) === modP(Y2 * Z1);\n }\n is0() {\n return this.equals(I);\n }\n /** Flip point over y coordinate. */\n negate() {\n return new Point(mod(-this.X), this.Y, this.Z, mod(-this.T));\n }\n /** Point doubling. Complete formula. Cost: `4M + 4S + 1*a + 6add + 1*2`. */\n double() {\n const { X: X1, Y: Y1, Z: Z1 } = this;\n const a = _a;\n // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#doubling-dbl-2008-hwcd\n const A = modP(X1 * X1);\n const B = modP(Y1 * Y1);\n const C = modP(2n * Z1 * Z1);\n const D = modP(a * A);\n const x1y1 = mod(X1 + Y1);\n const E = mod(modP(x1y1 * x1y1) - A - B);\n const G = mod(D + B);\n const F = mod(G - C);\n const H = mod(D - B);\n const X3 = modP(E * F);\n const Y3 = modP(G * H);\n const T3 = modP(E * H);\n const Z3 = modP(F * G);\n return new Point(X3, Y3, Z3, T3);\n }\n /** Point addition. Complete formula. Cost: `9M + 1*a + 1*d + 7add`. */\n add(other) {\n const { X: X1, Y: Y1, Z: Z1, T: T1 } = this;\n const { X: X2, Y: Y2, Z: Z2, T: T2 } = apoint(other); // doesn't check if other on-curve\n const a = _a;\n const d = _d;\n // https://hyperelliptic.org/EFD/g1p/auto-twisted-extended.html#addition-add-2008-hwcd\n const A = modP(X1 * X2);\n const B = modP(Y1 * Y2);\n const C = modP(modP(T1 * d) * T2);\n const D = modP(Z1 * Z2);\n const E = mod(modP(mod(X1 + Y1) * mod(X2 + Y2)) - A - B);\n const F = mod(D - C);\n const G = mod(D + C);\n const H = mod(B - modP(a * A));\n const X3 = modP(E * F);\n const Y3 = modP(G * H);\n const T3 = modP(E * H);\n const Z3 = modP(F * G);\n return new Point(X3, Y3, Z3, T3);\n }\n subtract(other) {\n return this.add(apoint(other).negate());\n }\n /**\n * Point-by-scalar multiplication. Safe mode requires `1 <= n < CURVE.n`.\n * Unsafe mode additionally permits `n = 0` and returns the identity point for that case.\n * Uses {@link wNAF} for base point.\n * Uses fake point to mitigate side-channel leakage.\n * @param n - scalar by which point is multiplied\n * @param safe - safe mode guards against timing attacks; unsafe mode is faster\n */\n multiply(n, safe = true) {\n // Mirror noble-curves: unsafe mode still validates scalar range first, but intentionally keeps\n // `n = 0` as the one extra accepted case used by verification-style callers.\n if (!safe && n === 0n)\n return I;\n arange(n, 1n, N);\n if (!safe && this.is0())\n return I;\n if (n === 1n)\n return this;\n if (this.equals(G))\n return wNAF(n).p;\n // init result point & fake point\n let p = I;\n let f = G;\n let d = this;\n // Safe mode always runs 256 iterations so ladder length can't leak the scalar's\n // leading zero bits; unsafe mode stops at the top set bit for speed.\n for (let i = 0; safe ? i < 256 : n > 0n; i++) {\n // if bit is present, add to point\n // if not present, add to fake, for timing safety\n if (n & 1n)\n p = p.add(d);\n else if (safe)\n f = f.add(d);\n d = d.double();\n n >>= 1n;\n }\n return p;\n }\n multiplyUnsafe(scalar) {\n return this.multiply(scalar, false);\n }\n /** Convert point to 2d xy affine point. (X, Y, Z) ∋ (x=X/Z, y=Y/Z) */\n toAffine() {\n const { X, Y, Z } = this;\n // Fast-path only for the identity point; all other inputs still go through inversion.\n if (this.equals(I))\n return { x: 0n, y: 1n };\n const iz = invert(Z, P);\n // (Z * Z^-1) must be 1, otherwise bad math\n if (modP(Z * iz) !== 1n)\n throw new Error('invalid inverse');\n // x = X*Z^-1; y = Y*Z^-1\n return { x: modP(X * iz), y: modP(Y * iz) };\n }\n toBytes() {\n const { x, y } = this.toAffine();\n const b = numTo32bLE(y);\n // store sign in first LE byte\n b[31] |= x & 1n ? 0x80 : 0;\n return b;\n }\n toHex() {\n return bytesToHex(this.toBytes());\n }\n clearCofactor() {\n return this.multiply(8n, false); // h = 8\n }\n isSmallOrder() {\n return this.clearCofactor().is0();\n }\n isTorsionFree() {\n // Multiply by big number N. We can't `mul(N)` because of checks. Instead, we `mul(N/2)*2+1`;\n // N is odd, so N/2 truncates and the final `add(this)` is always needed.\n return this.multiply(N / 2n, false)\n .double()\n .add(this)\n .is0();\n }\n}\n/** Generator / base point */\nconst G = new Point(Gx, Gy, 1n, mod(Gx * Gy));\n/** Identity / zero point */\nconst I = new Point(0n, 1n, 1n, 0n);\n// Static aliases\nPoint.BASE = G;\nPoint.ZERO = I;\nconst numTo32bLE = (num) => hexToBytes(padh(arange(num, 0n, B256), 64)).reverse();\n// Caller-enforced width: some sites require 32-byte RFC encodings, while others intentionally feed\n// wider SHA-512 output chunks through the same little-endian parser.\nconst bytesToNumberLE = (b) => BigInt('0x' + bytesToHex(Uint8Array.from(abytes(b)).reverse()));\nconst pow2 = (x, power) => {\n // pow2(x, 4) == x^(2^4)\n // Negative `power` values are not rejected here and currently leave `x` unchanged.\n let r = x;\n while (power-- > 0) {\n r = modP(r * r);\n }\n return r;\n};\n// prettier-ignore\nconst pow_2_252_3 = (x) => {\n const x2 = modP(x * x); // x^2, bits 1\n const b2 = modP(x2 * x); // x^3, bits 11\n const b4 = modP(pow2(b2, 2) * b2); // x^(2^4-1), bits 1111\n const b5 = modP(pow2(b4, 1) * x); // x^(2^5-1), bits 11111\n const b10 = modP(pow2(b5, 5) * b5); // x^(2^10-1)\n const b20 = modP(pow2(b10, 10) * b10); // x^(2^20-1)\n const b40 = modP(pow2(b20, 20) * b20); // x^(2^40-1)\n const b80 = modP(pow2(b40, 40) * b40); // x^(2^80-1)\n const b160 = modP(pow2(b80, 80) * b80); // x^(2^160-1)\n const b240 = modP(pow2(b160, 80) * b80); // x^(2^240-1)\n const b250 = modP(pow2(b240, 10) * b10); // x^(2^250-1)\n return modP(pow2(b250, 2) * x); // x^((p-5)/8), used by RFC8032 point decode\n};\nconst RM1 = 0x2b8324804fc1df0b2b4d00993dfbd7a72f431806ad2fe478c4ee1b274a0ea0b0n; // 2^((p-1)/4) = sqrt(-1)\n// RFC8032 §5.1.3 square-root helper for point decompression. `value` is only meaningful when\n// `isValid` is true; callers are also expected to pass canonical field elements with non-zero `v`.\n// prettier-ignore\nconst uvRatio = (u, v) => {\n const v3 = modP(v * modP(v * v)); // v³\n const v7 = modP(modP(v3 * v3) * v); // v⁷\n const pow = pow_2_252_3(modP(u * v7)); // (uv⁷)^(p-5)/8\n let x = modP(u * modP(v3 * pow)); // (uv³)(uv⁷)^(p-5)/8\n const vx2 = modP(v * modP(x * x)); // vx²\n const root1 = x; // First root candidate\n const root2 = modP(x * RM1); // Second root candidate; RM1 is √-1\n const useRoot1 = vx2 === u; // If vx² = u (mod p), x is a square root\n const useRoot2 = vx2 === mod(-u); // If vx² = -u, set x <-- x * 2^((p-1)/4)\n const noRoot = vx2 === mod(-u * RM1); // There is no valid root, vx² = -u√-1\n if (useRoot1)\n x = root1;\n if (useRoot2 || noRoot)\n x = root2; // We return root2 anyway, for const-time\n if ((mod(x) & 1n) === 1n)\n x = mod(-x); // edIsNegative\n return { isValid: useRoot1 || useRoot2, value: x };\n};\n// Reduce a little-endian byte string modulo the subgroup order `N` (RFC 8032's `L`); the `hash`\n// param name reflects the common caller shape, not an input restriction.\nconst modL_LE = (hash) => modN(bytesToNumberLE(hash));\n// RFC8032 5.1.5. Split the 64-byte hashed seed into the clamped scalar half and nonce prefix.\nconst hashedToExtK = (hashed) => {\n // slice creates a copy, unlike subarray\n const copy = snapshotBytes(hashed);\n const head = copy.slice(0, 32);\n head[0] &= 248; // Clamp bits: 0b1111_1000\n head[31] &= 127; // 0b0111_1111\n head[31] |= 64; // 0b0100_0000\n const prefix = copy.slice(32); // secret key \"prefix\"\n // RFC words this as `[s]B`; reducing the clamped little-endian scalar modulo `N` is equivalent\n // for base-point multiplication because `G` already has subgroup order `N`.\n const scalar = modL_LE(head);\n const point = G.multiply(scalar); // public key point\n const pointBytes = point.toBytes(); // point serialized to Uint8Array\n return { head, prefix, scalar, point, pointBytes };\n};\n// RFC8032 5.1.5; getPublicKey async, sync. Hash secret key and extract point.\nconst getExtendedPublicKeyAsync = (secretKey) => callHashAsync('sha512Async', abytes(secretKey, LEN, 'secretKey')).then(hashedToExtK);\nconst getExtendedPublicKey = (secretKey) => hashedToExtK(callHash('sha512', abytes(secretKey, LEN, 'secretKey')));\n/**\n * Creates a 32-byte Ed25519 public key from the RFC 8032 32-byte secret-key seed. Async.\n * @param secretKey - 32-byte RFC 8032 secret-key seed, not a 64-byte expanded secret key.\n * @returns 32-byte public key.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Derive the public key bytes for a newly generated signer secret.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const secretKey = ed.utils.randomSecretKey();\n * const publicKey = await ed.getPublicKeyAsync(secretKey);\n * ```\n */\nconst getPublicKeyAsync = (secretKey) => getExtendedPublicKeyAsync(secretKey).then((p) => p.pointBytes);\n/**\n * Creates a 32-byte Ed25519 public key from the RFC 8032 32-byte secret-key seed.\n * To use, set `hashes.sha512` first.\n * @param secretKey - 32-byte RFC 8032 secret-key seed, not a 64-byte expanded secret key.\n * @returns 32-byte public key.\n * @throws If synchronous SHA-512 has not been configured in `hashes`. {@link Error}\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Derive the public key entirely through the synchronous API.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const secretKey = ed.utils.randomSecretKey();\n * const publicKey = ed.getPublicKey(secretKey);\n * ```\n */\nconst getPublicKey = (secretKey) => getExtendedPublicKey(secretKey).pointBytes;\nconst hashFinishAsync = async (res) => res[1](await callHashAsync('sha512Async', res[0]));\nconst hashFinishSync = (res) => res[1](callHash('sha512', res[0]));\n// Code, shared between sync & async sign\nconst _sign = (e, rBytes, msg) => {\n const { pointBytes: A, scalar: s } = e;\n const r = modL_LE(rBytes); // r was created outside, reduce it modulo L\n // RFC 8032 5.1.6 allows r mod L = 0, and SUPERCOP ref10 accepts the resulting identity-point\n // signature.\n // We intentionally keep the safe multiply() rejection here so a miswired all-zero SHA-512 provider\n // fails loudly instead of silently producing a degenerate signature.\n const R = G.multiply(r).toBytes(); // R = [r]B\n const hashable = concatBytes(R, A, msg); // dom2(F, C) || R || A || PH(M)\n const finish = (hashed) => {\n // k = SHA512(dom2(F, C) || R || A || PH(M))\n const S = modN(r + modL_LE(hashed) * s); // S = (r + k * s) mod L; 0 <= s < l\n return abytes(concatBytes(R, numTo32bLE(S)), 64); // 64-byte sig: 32-byte encoded R point || 32-byte LE(S)\n };\n return [hashable, finish];\n};\n/**\n * Signs message using secret key. Async.\n * Follows RFC8032 5.1.6.\n * @param message - Message bytes to sign.\n * @param secretKey - 32-byte RFC 8032 secret-key seed, not a 64-byte expanded secret key.\n * @returns 64-byte Ed25519 signature.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Sign an arbitrary message with a fresh Ed25519 secret key.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const secretKey = ed.utils.randomSecretKey();\n * const message = new Uint8Array([1, 2, 3]);\n * const signature = await ed.signAsync(message, secretKey);\n * ```\n */\nconst signAsync = async (message, secretKey) => {\n const m = snapshotBytes(message, 'message');\n const e = await getExtendedPublicKeyAsync(secretKey);\n // r = SHA512(dom2(F, C) || prefix || PH(M)); then generate R, k, S and the signature.\n return hashFinishAsync(_sign(e, await callHashAsync('sha512Async', e.prefix, m), m));\n};\n/**\n * Signs message using secret key. To use, set `hashes.sha512` first.\n * Follows RFC8032 5.1.6.\n * @param message - Message bytes to sign.\n * @param secretKey - 32-byte RFC 8032 secret-key seed, not a 64-byte expanded secret key.\n * @returns 64-byte Ed25519 signature.\n * @throws If synchronous SHA-512 has not been configured in `hashes`. {@link Error}\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Use the sync API when you've wired a SHA-512 implementation yourself.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const secretKey = ed.utils.randomSecretKey();\n * const signature = ed.sign(new Uint8Array([1, 2, 3]), secretKey);\n * ```\n */\nconst sign = (message, secretKey) => {\n const m = snapshotBytes(message, 'message');\n const e = getExtendedPublicKey(secretKey);\n // r = SHA512(dom2(F, C) || prefix || PH(M)); then generate R, k, S and the signature.\n return hashFinishSync(_sign(e, callHash('sha512', e.prefix, m), m));\n};\n// Exported defaults favor ZIP-215 interoperability semantics; callers must opt into the stricter\n// branch with `{ zip215: false }`.\n// Preserves the exported ZIP-215 default for `{}` / `{ zip215: undefined }`, not just omitted opts.\nconst getZip215 = (options) => {\n if (options === null || typeof options !== 'object')\n throw new TypeError('expected valid options object');\n return options.zip215 ?? true;\n};\nconst _verify = (sig, msg, publicKey, options) => {\n sig = abytes(sig, 64, 'signature'); // Signature hex str/Bytes, must be 64 bytes\n msg = abytes(msg, undefined, 'message'); // Message hex str/Bytes\n publicKey = abytes(publicKey, LEN, 'publicKey');\n const zip215 = getZip215(options);\n // zip215=false keeps the library's stricter branch, which still canonicalizes `R` / `A` before\n // hashing and rejects small-order public keys earlier than pure RFC8032 text would require.\n const r = sig.subarray(0, LEN);\n const s = bytesToNumberLE(sig.subarray(LEN, 64)); // Decode second half as an integer S;\n let A, R, SB;\n let hashable = Uint8Array.of();\n let finished = false;\n try {\n // zip215=true is good for consensus-critical apps. =false follows RFC8032 / NIST186-5.\n // zip215=true: 0 <= y < MASK (2^256 for ed25519)\n // zip215=false: 0 <= y < P (2^255-19 for ed25519)\n A = Point.fromBytes(publicKey, zip215);\n R = Point.fromBytes(r, zip215);\n SB = G.multiply(s, false); // 0 <= s < l is done inside\n // ZIP-215 accepts noncanonical / unreduced point encodings, so the challenge hash must use the\n // exact signature/public-key bytes rather than canonicalized re-encodings of the decoded points.\n hashable = concatBytes(r, publicKey, msg); // dom2(F, C) || R || A || PH(M)\n finished = true;\n }\n catch (error) { }\n const finish = (hashed) => {\n if (!finished)\n return false;\n // Policy: strict mode intentionally rejects all small-order public keys, even though the raw RFC\n // equation text is looser here. This matches libsodium and avoids weak / ambiguous verification\n // outcomes where unusual low-order public keys can make distinct key/signature combinations verify.\n if (!zip215 && A.isSmallOrder())\n return false;\n // k = SHA512(dom2(F, C) || R || A || PH(M))\n const k = modL_LE(hashed);\n const RkA = R.add(A.multiply(k, false));\n // Extended group equation\n // [8][S]B = [8]R + [8][k]A'\n return RkA.subtract(SB).clearCofactor().is0();\n };\n return [hashable, finish];\n};\n/**\n * Verifies a signature on message and public key. Async.\n * The implementation is based on RFC8032 5.1.7, but default opts use ZIP-215 semantics; pass\n * `{ zip215: false }` for the library's stricter branch.\n * @param signature - 64-byte signature.\n * @param message - Signed message bytes.\n * @param publicKey - 32-byte public key.\n * @param opts - Verification options. Defaults to ZIP-215 semantics. See {@link EdDSAVerifyOpts}.\n * @returns `true` when the signature is valid.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Verify the signature against the same message and derived public key.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const secretKey = ed.utils.randomSecretKey();\n * const message = new Uint8Array([1, 2, 3]);\n * const publicKey = await ed.getPublicKeyAsync(secretKey);\n * const signature = await ed.signAsync(message, secretKey);\n * const isValid = await ed.verifyAsync(signature, message, publicKey);\n * ```\n */\nconst verifyAsync = async (signature, message, publicKey, opts = {}) => hashFinishAsync(_verify(signature, message, publicKey, opts));\n/**\n * Verifies a signature on message and public key using the synchronous hash path.\n * The implementation is based on RFC8032 5.1.7, but default opts use ZIP-215 semantics; pass\n * `{ zip215: false }` for the library's stricter branch.\n * @param signature - 64-byte signature.\n * @param message - Signed message bytes.\n * @param publicKey - 32-byte public key.\n * @param opts - Verification options. Defaults to ZIP-215 semantics. See {@link EdDSAVerifyOpts}.\n * @returns `true` when the signature is valid.\n * @throws If synchronous SHA-512 has not been configured in `hashes`. {@link Error}\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Verify a signature entirely through the synchronous API.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const secretKey = ed.utils.randomSecretKey();\n * const message = new Uint8Array([1, 2, 3]);\n * const publicKey = ed.getPublicKey(secretKey);\n * const signature = ed.sign(message, secretKey);\n * const isValid = ed.verify(signature, message, publicKey);\n * ```\n */\nconst verify = (signature, message, publicKey, opts = {}) => hashFinishSync(_verify(signature, message, publicKey, opts));\n/**\n * Math, hex, byte helpers. Not in `utils` because utils share API with noble-curves.\n * Exposes the same low-level field-default `mod` reducer and non-CT `invert` helper used\n * internally.\n * @example\n * Convert bytes to a hex string with the low-level helper namespace.\n *\n * ```ts\n * const hex = etc.bytesToHex(new Uint8Array([1, 2, 3]));\n * ```\n */\nconst etc = /* @__PURE__ */ freeze({\n bytesToHex,\n hexToBytes,\n concatBytes,\n mod,\n invert,\n randomBytes,\n});\n/**\n * Hash implementations used by the synchronous API plus the default async WebCrypto provider.\n * Both slots are configurable API surface; wrapper helpers revalidate that providers still return\n * 64-byte SHA-512 digests.\n * @example\n * Provide a SHA-512 implementation before calling synchronous helpers.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const { publicKey } = ed.keygen();\n * ```\n */\nconst hashes = {\n sha512Async: async (message) => {\n const s = globalThis?.crypto?.subtle;\n if (!s)\n throw new Error('crypto.subtle must be defined, consider polyfill');\n return new Uint8Array(await s.digest('SHA-512', concatBytes(message)));\n },\n sha512: undefined,\n};\n// Returns the final 32-byte Ed25519 secret-key seed verbatim, generating fresh random bytes only\n// when omitted.\nconst randomSecretKey = (seed) => {\n return abytes(seed === undefined ? randomBytes() : seed, LEN, 'seed');\n};\n/**\n * Generates a secret/public keypair.\n * @param seed - Optional 32-byte Ed25519 secret-key seed, returned verbatim as `secretKey`.\n * @returns Keypair with `secretKey` and `publicKey`.\n * @throws If synchronous SHA-512 has not been configured in `hashes`. {@link Error}\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Generate a new keypair through the synchronous API after wiring SHA-512.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n * import { sha512 } from '@noble/hashes/sha2.js';\n *\n * ed.hashes.sha512 = sha512;\n * const { secretKey, publicKey } = ed.keygen();\n * ```\n */\nconst keygen = (seed) => {\n const secretKey = randomSecretKey(seed);\n const publicKey = getPublicKey(secretKey);\n return { secretKey, publicKey };\n};\n/**\n * Generates a secret/public keypair asynchronously.\n * @param seed - Optional 32-byte Ed25519 secret-key seed, returned verbatim as `secretKey`.\n * @returns Keypair with `secretKey` and `publicKey`.\n * @throws On wrong argument types. {@link TypeError}\n * @throws On wrong argument ranges or values. {@link RangeError}\n * @example\n * Generate a new keypair through the asynchronous WebCrypto-backed path.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const { secretKey, publicKey } = await ed.keygenAsync();\n * ```\n */\nconst keygenAsync = async (seed) => {\n const secretKey = randomSecretKey(seed);\n const publicKey = await getPublicKeyAsync(secretKey);\n return { secretKey, publicKey };\n};\n/**\n * Ed25519-specific key utilities.\n * `utils.getExtendedPublicKey*` expose secret-derived internals (`head`, `prefix`, `scalar`, and\n * point objects), not just public-key bytes.\n * @example\n * Generate a new Ed25519 secret key and derive the matching public key.\n *\n * ```ts\n * import * as ed from '@noble/ed25519';\n *\n * const secretKey = ed.utils.randomSecretKey();\n * const publicKey = await ed.getPublicKeyAsync(secretKey);\n * ```\n */\nconst utils = /* @__PURE__ */ freeze({\n getExtendedPublicKeyAsync,\n getExtendedPublicKey,\n randomSecretKey,\n});\n// ## Precomputes\n// --------------\n// Fixed W=8 window: 33 windows (ceil(256/8) + 1, NOT 32 - see wNAF loop), 128 points per window.\n// Layout is grouped by window: each block stores the positive multiples `1*base .. 128*base` for\n// that window, and the extra `+1` window absorbs carries from signed-digit recoding.\nconst precompute = () => {\n const points = [];\n let p = G;\n let b;\n for (let w = 0; w < 33; w++) {\n b = p;\n points.push(b);\n for (let i = 1; i < 128; i++) {\n b = b.add(p);\n points.push(b);\n } // i=1, bc we skip 0\n p = b.double();\n }\n return points;\n};\nlet Gpows = undefined; // shared process-wide cache of base-point precomputes\n// Branch-based negate helper used for JS/JIT mitigation symmetry, not a strict constant-time claim.\nconst ctneg = (cnd, p) => {\n const n = p.negate();\n return cnd ? n : p;\n};\n/**\n * Precomputes give 12x faster getPublicKey(), 10x sign(), 2x verify() by\n * caching multiples of G (base point). Cache is stored in 32MB of RAM.\n * Any time `G.multiply` is done, precomputes are used.\n * Not used for getSharedSecret, which instead multiplies random pubkey `P.multiply`.\n *\n * w-ary non-adjacent form (wNAF) precomputation method is 10% slower than windowed method,\n * but takes 2x less RAM. RAM reduction is possible by utilizing `.subtract`.\n * Returns the real accumulator `p` plus a fake accumulator `f`; callers only care about `p`, while\n * `f` exists to keep similar work in zero-digit branches as a JS/JIT side-channel mitigation.\n *\n * !! Precomputes can be disabled by commenting-out call of the wNAF() inside Point#multiply().\n */\nconst wNAF = (n) => {\n const comp = Gpows || (Gpows = precompute());\n let p = I;\n let f = G; // f must be G, or could become I in the end\n for (let w = 0; w < 33; w++) {\n let wbits = Number(n & 255n); // extract W=8 bits.\n n >>= 8n; // shift number by W=8 bits.\n // We use negative indexes to reduce size of precomputed table by 2x.\n // Instead of needing precomputes 0..256, we only calculate them for 0..128.\n // If an index > 128 is found, we do (256-index) - where 256 is next window.\n // Naive: index +127 => 127, +224 => 224\n // Optimized: index +127 => 127, +224 => 256-32\n if (wbits > 128) {\n wbits -= 256;\n n += 1n;\n }\n const off = w * 128; // offset of this window's block; also the fake-add index\n const offP = off + Math.abs(wbits) - 1; // real-add index; both offsets always evaluated\n const isOddW = w % 2 !== 0; // conditions, evaluate both; alternates fake-add sign per window\n const isNeg = wbits < 0;\n if (wbits === 0) {\n // wbits == 0 means the real index would be I: can't add it. Add window offset `off` instead.\n f = f.add(ctneg(isOddW, comp[off])); // bits are 0: add garbage to fake point\n }\n else {\n p = p.add(ctneg(isNeg, comp[offP])); // bits are 1: add to result point\n }\n }\n if (n !== 0n)\n throw new Error('invalid wnaf');\n return { p, f }; // return both real and fake points for JIT/leakage-shape symmetry\n};\n// !! Remove the export to easily use in REPL / browser console\nexport { etc, getPublicKey, getPublicKeyAsync, hash, hashes, keygen, keygenAsync, Point, sign, signAsync, utils, verify, verifyAsync, };\n","/**\n * The public keys this build of the SDK will accept licence signatures from.\n *\n * **This file contains public keys only.** BroadPaper's private signing key\n * lives in the licence issuer's secret store and is never in this repository,\n * never in the npm package and never in a browser bundle. Publishing the\n * public half is the point: it is what lets a licence be checked with no\n * network call.\n *\n * Add a production key with:\n *\n * node scripts/licence-keys.mjs --production --key-id bp-1\n *\n * which prints the private key once, for the operator to paste into the\n * issuer's configuration, and writes the public half into this array.\n *\n * The list is an allowlist, so it is also the rotation mechanism: issue with a\n * new `keyId`, ship an SDK release trusting both, and drop the old entry once\n * every licence signed with it has expired. Licences carry their `keyId` inside\n * the signed payload, so an attacker cannot point one at a different key.\n *\n * It starts empty on purpose. A key here is trusted by every copy of the SDK in\n * the world, including production installs, which is exactly why a development\n * key must never be added to it — development keys are supplied at runtime\n * instead, through `configure({ trustedKeys })` or `BROADPAPER_TRUSTED_KEYS`,\n * so a licence signed in development cannot be honoured by a production build.\n */\nimport type { TrustedKey } from \"./types.js\";\n\nexport const TRUSTED_KEYS: readonly TrustedKey[] = [\n { keyId: \"bp-2026\", publicKey: \"woKmWyIazae7SpGhi4dwA7zNK1lWdboq88Rl5xscTs4\", note: \"production, generated 2026-09-08\" }\n];\n","/**\n * The licence certificate and the states it can be in.\n *\n * A BroadPaper licence is a signed certificate, not a secret. It says who\n * bought what and until when, BroadPaper signs it, and the SDK checks that\n * signature with a public key compiled into the package. Nothing here talks to\n * a network, reads a machine identifier or writes a file: a licence that is\n * valid on a laptop with no route to the internet is valid, full stop.\n */\n\n/**\n * What the licence permits. Not a feature gate — both entitlements unlock\n * exactly the same software. The difference is who the resulting application\n * may be put in front of, which is a contractual matter and is presented as\n * one in the account area and the licence agreement.\n */\nexport type Entitlement = \"internal\" | \"saas\";\n\n/** The product a licence is for. Present so one signing key can serve more later. */\nexport const PRODUCT = \"broadpaper-sdk\";\n\n/**\n * The signed payload.\n *\n * `customerId` is the durable identifier of the buying organisation — a Clerk\n * organisation id — rather than an email address, because people change\n * addresses and organisations outlive their founders.\n *\n * Times are epoch **seconds**, not milliseconds: the payload is base64'd into\n * a string a developer will paste into a config file, and three characters per\n * timestamp is three characters.\n */\nexport interface LicensePayload {\n /** Payload schema version. Bumped only when the meaning of a field changes. */\n version: 1;\n /** Which signing key signed this. Lets keys be rotated without reissuing everything. */\n keyId: string;\n /**\n * BroadPaper's own identifier for *this certificate*, `lic_…`.\n *\n * One per issuance, so a renewal or an upgrade carries a new one and the\n * document it produced can be dated from it. The customer is identified by\n * `customerId`, which does not change.\n */\n licenseId: string;\n /** The licensed organisation's durable id. */\n customerId: string;\n /** The organisation's name, for display in warnings and PDF metadata. */\n customerName: string;\n product: typeof PRODUCT;\n entitlement: Entitlement;\n /** Epoch seconds. */\n issuedAt: number;\n /** Epoch seconds. */\n expiresAt: number;\n}\n\n/**\n * Why a licence is not being honoured, or how it is being honoured.\n *\n * These are deliberately coarse. A developer needs to know whether their PDFs\n * will carry the evaluation mark and, if so, what to do about it; a taxonomy of\n * eleven parse failures helps nobody.\n */\nexport type LicenseState =\n /** No licence was configured. The SDK works; PDFs carry the evaluation mark. */\n | \"unlicensed\"\n /** A licence was configured but could not be read, or its signature is wrong. */\n | \"invalid\"\n /** Signed by a key this build of the SDK does not trust. */\n | \"untrusted\"\n /** For a different product, or a payload version this SDK is older than. */\n | \"unsupported\"\n /** Valid, signed, and inside its term. */\n | \"active\"\n /** Past `expiresAt` but inside the grace period: honoured, and warned about. */\n | \"grace\"\n /** Past `expiresAt` and past the grace period. */\n | \"expired\";\n\n/** The outcome of checking a licence. Everything the SDK needs to decide. */\nexport interface LicenseStatus {\n state: LicenseState;\n /** True when PDFs render clean. `active` and `grace` only. */\n licensed: boolean;\n /** The payload, when one could be read and verified. */\n payload: LicensePayload | null;\n /** What the licence permits, when it is being honoured. */\n entitlement: Entitlement | null;\n /** Expiry as a Date, when known. */\n expiresAt: Date | null;\n /** Days until expiry; negative once expired. Null when there is no licence. */\n daysRemaining: number | null;\n /**\n * A developer-facing sentence. Always present for a state that is not\n * `active`, so callers can log it without composing their own prose.\n */\n message: string | null;\n}\n\n/** A public key this build of the SDK will accept signatures from. */\nexport interface TrustedKey {\n /** Matches `keyId` in the payload. */\n keyId: string;\n /** The raw 32-byte Ed25519 public key, base64url or base64. */\n publicKey: string;\n /** Free text for the key's provenance. Never displayed to end users. */\n note?: string;\n}\n","/**\n * Offline licence verification.\n *\n * Everything here is local: a signature check against a compiled-in public key\n * and a comparison against the clock. There is no activation call, no licence\n * server and nothing to be offline from. That is a deliberate product decision\n * as much as a technical one — a report renderer that stops working because a\n * key server is down is a report renderer nobody puts in a payroll run.\n *\n * The failure modes are all *soft*. An unreadable licence never throws out of a\n * render; it produces a status whose `message` says what is wrong, and the PDF\n * comes out carrying the evaluation mark.\n */\nimport { verifyAsync } from \"@noble/ed25519\";\nimport { base64UrlToBytes, utf8ToBytes } from \"./encoding.js\";\nimport { LicenseFormatError, parseLicense } from \"./format.js\";\nimport { TRUSTED_KEYS } from \"./trusted-keys.js\";\nimport { PRODUCT, type LicensePayload, type LicenseStatus, type TrustedKey } from \"./types.js\";\n\n/**\n * How long an expired licence keeps working.\n *\n * A renewal that is a week late is an accounts payable problem, not a reason to\n * stamp a customer's month-end reports. Thirty days is long enough to cover a\n * card expiring over a holiday and short enough that it is not a second licence\n * term.\n */\nexport const DEFAULT_GRACE_PERIOD_DAYS = 30;\n\nconst DAY_MS = 86_400_000;\n\nexport interface VerifyOptions {\n /** Fixed clock. Tests and deterministic renders pass one. */\n now?: Date;\n /** Extra keys to trust, on top of the ones built into this SDK. */\n trustedKeys?: readonly TrustedKey[];\n /** Overrides {@link DEFAULT_GRACE_PERIOD_DAYS}. */\n gracePeriodDays?: number;\n}\n\n/** The status of a caller that supplied no licence at all. */\nexport function unlicensed(): LicenseStatus {\n return {\n state: \"unlicensed\",\n licensed: false,\n payload: null,\n entitlement: null,\n expiresAt: null,\n daysRemaining: null,\n message:\n \"No BroadPaper licence is configured, so PDFs carry the evaluation watermark. Everything else works; see https://www.broadpaper.com/docs/guide/licensing.\"\n };\n}\n\nfunction failure(state: LicenseStatus[\"state\"], message: string, payload: LicensePayload | null = null): LicenseStatus {\n return {\n state,\n licensed: false,\n payload,\n entitlement: null,\n expiresAt: payload ? new Date(payload.expiresAt * 1000) : null,\n daysRemaining: null,\n message\n };\n}\n\n/**\n * Checks a licence string and reports what it entitles the caller to.\n *\n * Never throws for a bad licence: a malformed string, a forged signature and an\n * expired term are all ordinary answers, and a render is not the place to\n * discover that a config file has a typo in it.\n */\nexport async function verifyLicense(license: string | null | undefined, options: VerifyOptions = {}): Promise<LicenseStatus> {\n if (!license || !license.trim()) return unlicensed();\n\n let parsed;\n try {\n parsed = parseLicense(license);\n } catch (e) {\n if (e instanceof LicenseFormatError) {\n return failure(\n e.kind,\n e.kind === \"unsupported\"\n ? `This BroadPaper licence needs a newer version of the SDK (${e.message}). Update @broadpaper/* or the PDF will carry the evaluation watermark.`\n : `The BroadPaper licence could not be read (${e.message}), so PDFs carry the evaluation watermark.`\n );\n }\n /* c8 ignore next -- parseLicense only throws LicenseFormatError */\n throw e;\n }\n\n const { payload } = parsed;\n if (payload.product !== PRODUCT) {\n return failure(\n \"invalid\",\n `This licence is for ${JSON.stringify(payload.product)}, not the BroadPaper SDK, so PDFs carry the evaluation watermark.`,\n payload\n );\n }\n\n const key = findKey(payload.keyId, options.trustedKeys);\n if (!key) {\n return failure(\n \"untrusted\",\n `This BroadPaper licence was signed with key ${JSON.stringify(payload.keyId)}, which this build does not trust. ` +\n \"A licence issued for development is not honoured by a production build; check BROADPAPER_LICENSE points at the right one.\",\n payload\n );\n }\n\n let signatureOk = false;\n try {\n signatureOk = await verifyAsync(parsed.signature, utf8ToBytes(parsed.signedText), base64UrlToBytes(key.publicKey));\n } catch {\n // A malformed public key or a point that is not on the curve. Either way\n // this licence is not going to verify, and a render must not fail over it.\n signatureOk = false;\n }\n if (!signatureOk) {\n return failure(\"invalid\", \"This BroadPaper licence failed its signature check — it has been altered or truncated. PDFs carry the evaluation watermark.\", payload);\n }\n\n const now = options.now ?? new Date();\n const expiresAt = new Date(payload.expiresAt * 1000);\n const graceDays = options.gracePeriodDays ?? DEFAULT_GRACE_PERIOD_DAYS;\n const msRemaining = expiresAt.getTime() - now.getTime();\n const daysRemaining = Math.floor(msRemaining / DAY_MS);\n\n if (msRemaining > 0) {\n return {\n state: \"active\",\n licensed: true,\n payload,\n entitlement: payload.entitlement,\n expiresAt,\n daysRemaining,\n message: null\n };\n }\n\n if (msRemaining > -graceDays * DAY_MS) {\n const daysOver = Math.max(1, Math.ceil(-msRemaining / DAY_MS));\n return {\n state: \"grace\",\n licensed: true,\n payload,\n entitlement: payload.entitlement,\n expiresAt,\n daysRemaining,\n message:\n `The BroadPaper licence for ${payload.customerName} expired ${daysOver} day${daysOver === 1 ? \"\" : \"s\"} ago and is inside its ${graceDays}-day grace period. ` +\n \"Renew it and copy the new licence from your account, or PDFs will start carrying the evaluation watermark.\"\n };\n }\n\n return failure(\n \"expired\",\n `The BroadPaper licence for ${payload.customerName} expired on ${expiresAt.toISOString().slice(0, 10)} and its ${graceDays}-day grace period has passed, ` +\n \"so PDFs carry the evaluation watermark. Renewing issues a new licence in your BroadPaper account.\",\n payload\n );\n}\n\nfunction findKey(keyId: string, extra: readonly TrustedKey[] | undefined): TrustedKey | undefined {\n // Runtime keys are searched first so a development key can shadow a built-in\n // one of the same name without a rebuild.\n return extra?.find((k) => k.keyId === keyId) ?? TRUSTED_KEYS.find((k) => k.keyId === keyId);\n}\n","/**\n * Configuring BroadPaper once, for the life of the process.\n *\n * import { BroadPaper } from \"@broadpaper/forme\";\n * BroadPaper.configure({ license: process.env.BROADPAPER_LICENSE });\n *\n * The licence is not a credential, so this is not a secrets API: it is the same\n * shape of thing as setting a locale. A browser bundle that carries the licence\n * string in plain text is fine — the string is a signed certificate, and\n * possessing it grants nothing beyond what its payload already says.\n *\n * Configuration is deliberately process-global rather than an argument to every\n * render. Threading a licence through `renderPdf`, the render service, the\n * batch endpoint, the .NET client and every future export path is exactly the\n * kind of plumbing that ends with one path quietly forgetting it, and a\n * customer who has paid discovering a watermark in production.\n *\n * The store hangs off a `Symbol.for` key rather than a module-level variable so\n * that two copies of this package in one dependency tree — the usual result of\n * a mixed-version install — still agree about the licence.\n */\nimport { unlicensed, verifyLicense, type VerifyOptions } from \"./verify.js\";\nimport type { LicenseStatus, TrustedKey } from \"./types.js\";\n\nexport interface BroadPaperConfig {\n /**\n * The licence string, `BP1.…`. Read from `BROADPAPER_LICENSE` when this is\n * not set and the runtime has environment variables.\n */\n license?: string | null;\n /**\n * Public keys to trust in addition to the ones built into the SDK. This is\n * how a development licence is honoured on a developer's machine without a\n * development key ever being trusted by a production build.\n */\n trustedKeys?: readonly TrustedKey[];\n /** Overrides the 30-day post-expiry grace period. Mostly for tests. */\n gracePeriodDays?: number;\n /** Where licence warnings go. Defaults to `console.warn`. */\n logger?: ((message: string) => void) | null;\n}\n\ninterface Store {\n config: BroadPaperConfig;\n /** Memoised by the licence string that produced it. */\n cache: { key: string; status: Promise<LicenseStatus> } | null;\n /** Messages already logged, so a hundred renders do not print a hundred lines. */\n logged: Set<string>;\n}\n\nconst STORE_KEY = Symbol.for(\"broadpaper.license.store\");\n\nfunction store(): Store {\n const g = globalThis as Record<symbol, unknown>;\n let s = g[STORE_KEY] as Store | undefined;\n if (!s) {\n s = { config: {}, cache: null, logged: new Set() };\n g[STORE_KEY] = s;\n }\n return s;\n}\n\n/**\n * Sets the licence and any other SDK-wide options. Call it once, at startup.\n *\n * Successive calls merge, so a host can set the licence in one place and the\n * grace period in another; passing `license: null` clears it.\n */\nexport function configure(config: BroadPaperConfig): void {\n const s = store();\n s.config = { ...s.config, ...config };\n s.cache = null;\n s.logged.clear();\n}\n\n/** What {@link configure} has been given, plus whatever the environment supplies. */\nexport function getConfig(): BroadPaperConfig {\n return { ...store().config };\n}\n\n/** Forgets the configuration entirely. Exists for tests. */\nexport function resetConfig(): void {\n const g = globalThis as Record<symbol, unknown>;\n delete g[STORE_KEY];\n}\n\n/**\n * `BroadPaper.configure({ … })`, for hosts that prefer a namespace to a bare\n * function. Both are the same store.\n */\nexport const BroadPaper = { configure, getConfig };\n\nfunction env(name: string): string | undefined {\n // Node, Deno and bundlers that inline `process.env` all satisfy this; a\n // browser without a shim simply has no environment, which is not an error.\n const p = (globalThis as { process?: { env?: Record<string, string | undefined> } }).process;\n const value = p?.env?.[name];\n return value && value.trim() ? value : undefined;\n}\n\n/**\n * Keys trusted in addition to the built-in ones, from configuration and from\n * `BROADPAPER_TRUSTED_KEYS` — a JSON array of `{ keyId, publicKey }`.\n *\n * A syntax error there is reported rather than swallowed: someone setting that\n * variable is doing so on purpose, and silently ignoring it would present as\n * \"my development licence is not being honoured\" with nothing to go on.\n */\nfunction trustedKeysFromEnv(): readonly TrustedKey[] {\n const raw = env(\"BROADPAPER_TRUSTED_KEYS\");\n if (!raw) return [];\n try {\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) throw new Error(\"expected a JSON array\");\n return parsed.map((entry, i) => {\n const k = entry as Record<string, unknown>;\n if (typeof k?.keyId !== \"string\" || typeof k?.publicKey !== \"string\") throw new Error(`entry ${i} needs keyId and publicKey`);\n return { keyId: k.keyId, publicKey: k.publicKey };\n });\n } catch (e) {\n warn(`BROADPAPER_TRUSTED_KEYS could not be read (${(e as Error).message}); it is being ignored.`);\n return [];\n }\n}\n\n/** Logs a message once, whatever it takes to reach the developer. */\nexport function warn(message: string): void {\n const s = store();\n if (s.logged.has(message)) return;\n s.logged.add(message);\n const logger = s.config.logger;\n if (logger === null) return;\n const line = `[BroadPaper] ${message}`;\n if (logger) logger(line);\n else console.warn(line);\n}\n\nexport interface ResolveOptions extends VerifyOptions {\n /** A licence for this call only, overriding the configured one. */\n license?: string | null;\n}\n\n/**\n * The licence status for the current configuration.\n *\n * Memoised on the licence string, because every PDF asks and a signature check\n * per page of a five-hundred-page batch is waste. `configure` clears it, and a\n * per-call `license` bypasses it.\n *\n * Whatever the answer, any developer-facing message is logged once. That is the\n * only thing the SDK does that a caller did not ask for, and it is the\n * difference between a developer seeing \"your licence expired\" and a developer\n * seeing an unexplained watermark.\n */\nexport async function resolveLicenseStatus(options: ResolveOptions = {}): Promise<LicenseStatus> {\n const s = store();\n const config = s.config;\n const license = options.license !== undefined ? options.license : config.license ?? env(\"BROADPAPER_LICENSE\") ?? null;\n const trustedKeys = [...(options.trustedKeys ?? []), ...(config.trustedKeys ?? []), ...trustedKeysFromEnv()];\n const gracePeriodDays = options.gracePeriodDays ?? config.gracePeriodDays;\n\n if (!license) {\n const status = unlicensed();\n if (status.message) warn(status.message);\n return status;\n }\n\n const verify = (): Promise<LicenseStatus> =>\n verifyLicense(license, { ...(options.now ? { now: options.now } : {}), trustedKeys, ...(gracePeriodDays !== undefined ? { gracePeriodDays } : {}) }).then((status) => {\n if (status.message) warn(status.message);\n return status;\n });\n\n // A fixed clock is a test or a deterministic render; caching across different\n // clocks would make the grace-period boundary depend on call order.\n if (options.now || options.license !== undefined) return verify();\n\n const key = `${license}|${trustedKeys.map((k) => k.keyId).join(\",\")}|${gracePeriodDays ?? \"\"}`;\n if (s.cache?.key !== key) s.cache = { key, status: verify() };\n return s.cache.status;\n}\n","/**\n * The evaluation mark.\n *\n * This is the only thing an unlicensed BroadPaper does differently. Every\n * block, both PDF backends, the designer, data binding, pagination and the\n * render service behave identically with and without a licence; what changes is\n * that the file says, on every page, that it was produced with an evaluation\n * copy.\n *\n * It is drawn to be unmistakable in a document review and harmless to a\n * developer evaluating the product: a light diagonal line across the page,\n * behind nothing and over everything, at an opacity that leaves the report\n * entirely readable. Making the output illegible would only push people towards\n * evaluating something else.\n *\n * Each backend draws the spec with its own primitives — the Forme engine has a\n * page-native watermark node, Chromium gets a printed overlay — because a\n * single drawing implementation would mean one of them post-processing a file\n * the other had already finished, and a stamping pass that can be skipped is a\n * stamping pass that eventually is.\n */\nimport { resolveLicenseStatus, type ResolveOptions } from \"./config.js\";\nimport type { LicenseStatus } from \"./types.js\";\n\nexport interface WatermarkSpec {\n text: string;\n /** Points. The engines size the mark from this, not from the page. */\n fontSize: number;\n /** Degrees, anticlockwise from horizontal. */\n angle: number;\n /** Hex, without alpha. */\n color: string;\n /** 0–1. */\n opacity: number;\n}\n\n/**\n * The mark itself.\n *\n * No dashes or typographic punctuation: the standard PDF faces carry no em\n * dash, and a theme that names a font the engine does not have falls back to\n * them, which turned \"BroadPaper — Evaluation Copy\" into \"BroadPaper\n * Evaluation Copy\" in half the documents and a question mark in the rest.\n */\nexport const EVALUATION_WATERMARK: WatermarkSpec = {\n text: \"BroadPaper Evaluation Copy\",\n fontSize: 44,\n angle: -35,\n color: \"#c8102e\",\n opacity: 0.12\n};\n\n/**\n * The mark a render should carry, or null when the licence says none.\n *\n * Backends call this rather than reading the licence status themselves, so\n * \"licensed\" and \"no watermark\" cannot drift apart.\n */\nexport async function resolveWatermark(options: ResolveOptions = {}): Promise<WatermarkSpec | null> {\n const status = await resolveLicenseStatus(options);\n return watermarkFor(status);\n}\n\n/** The pure half of {@link resolveWatermark}, for callers that already have a status. */\nexport function watermarkFor(status: LicenseStatus): WatermarkSpec | null {\n return status.licensed ? null : EVALUATION_WATERMARK;\n}\n\n/**\n * CSS that paints the mark on every `.bp-page` of a rendered document.\n *\n * Used by the Chromium backend and by the designer's print path — the two\n * places a PDF is produced by a browser rather than by the engine. `position:\n * fixed` would put it on the viewport rather than on each page, so it is an\n * absolutely positioned pseudo-element on the page box, which prints once per\n * sheet.\n *\n * `print-color-adjust` matters: without it Chromium drops the mark from the\n * printed file exactly as it drops any other background colour.\n */\nexport function watermarkCss(spec: WatermarkSpec = EVALUATION_WATERMARK): string {\n const text = spec.text.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n return [\n \".bp-page{position:relative;}\",\n \".bp-page::after{\",\n `content:\"${text}\";`,\n \"position:absolute;inset:0;\",\n \"display:flex;align-items:center;justify-content:center;\",\n \"pointer-events:none;z-index:2147483647;\",\n `transform:rotate(${spec.angle}deg);`,\n \"font-family:Helvetica,Arial,sans-serif;font-weight:700;letter-spacing:0.04em;white-space:nowrap;\",\n `font-size:${spec.fontSize}pt;color:${spec.color};opacity:${spec.opacity};`,\n \"-webkit-print-color-adjust:exact;print-color-adjust:exact;\",\n \"}\"\n ].join(\"\");\n}\n\n/**\n * The PDF Producer string for a render.\n *\n * Licensed output records the licence id. It is not a secret — it identifies a\n * customer's licence, not their account — and having it in the file means a\n * document that turns up somewhere it should not can be traced back to the\n * licence that produced it without any of the tracking a phone-home would need.\n */\nexport function producerString(status: LicenseStatus): string {\n if (!status.licensed || !status.payload) return \"BroadPaper (evaluation)\";\n return `BroadPaper (${status.payload.licenseId})`;\n}\n","import { lookup } from \"node:dns/promises\";\nimport { isIP } from \"node:net\";\n\nexport interface NetworkPolicy {\n /**\n * Hostnames (or `*.example.com` wildcards, or `*`) the renderer may fetch\n * assets from. `data:` URLs are always allowed. Default: none.\n */\n allowedHosts?: string[];\n /** Block private / loopback / link-local address ranges even for allowed hosts. Default true. */\n blockPrivateNetworks?: boolean;\n /** Maximum number of network requests per render. Default 200. */\n maxRequests?: number;\n}\n\nconst PRIVATE_V4 = [\n [/^10\\./, \"10/8\"],\n [/^127\\./, \"loopback\"],\n [/^169\\.254\\./, \"link-local\"],\n [/^172\\.(1[6-9]|2\\d|3[01])\\./, \"172.16/12\"],\n [/^192\\.168\\./, \"192.168/16\"],\n [/^0\\./, \"0/8\"],\n [/^100\\.(6[4-9]|[7-9]\\d|1[01]\\d|12[0-7])\\./, \"CGNAT\"]\n] as const;\n\nexport function isPrivateAddress(ip: string): boolean {\n const kind = isIP(ip);\n if (kind === 4) return PRIVATE_V4.some(([re]) => re.test(ip));\n if (kind === 6) {\n const lower = ip.toLowerCase();\n if (lower === \"::1\" || lower === \"::\") return true;\n if (lower.startsWith(\"fe80:\") || lower.startsWith(\"fc\") || lower.startsWith(\"fd\")) return true;\n const mapped = /^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/.exec(lower);\n if (mapped) return isPrivateAddress(mapped[1]!);\n return false;\n }\n return false;\n}\n\nexport function hostAllowed(host: string, allowed: string[] | undefined): boolean {\n if (!allowed || allowed.length === 0) return false;\n const h = host.toLowerCase();\n return allowed.some((pattern) => {\n const p = pattern.toLowerCase();\n if (p === \"*\") return true;\n if (p.startsWith(\"*.\")) return h === p.slice(2) || h.endsWith(p.slice(1));\n return h === p;\n });\n}\n\nexport interface RequestDecision {\n allow: boolean;\n reason?: string;\n}\n\n/**\n * Decides whether the headless browser may perform a request. Resolves DNS so\n * that a public hostname pointing at a private address is still blocked.\n */\nexport async function decideRequest(url: string, policy: NetworkPolicy, counter: { count: number }): Promise<RequestDecision> {\n if (url.startsWith(\"data:\") || url === \"about:blank\") return { allow: true };\n let u: URL;\n try {\n u = new URL(url);\n } catch {\n return { allow: false, reason: \"invalid URL\" };\n }\n if (u.protocol !== \"http:\" && u.protocol !== \"https:\") return { allow: false, reason: `scheme ${u.protocol} not allowed` };\n if (++counter.count > (policy.maxRequests ?? 200)) return { allow: false, reason: \"request limit exceeded\" };\n if (!hostAllowed(u.hostname, policy.allowedHosts)) return { allow: false, reason: `host ${u.hostname} not in allow-list` };\n if (policy.blockPrivateNetworks !== false) {\n const host = u.hostname.replace(/^\\[|\\]$/g, \"\");\n if (host === \"localhost\" || host.endsWith(\".localhost\") || host.endsWith(\".internal\")) return { allow: false, reason: \"private host\" };\n if (isIP(host)) {\n if (isPrivateAddress(host)) return { allow: false, reason: \"private address\" };\n } else {\n try {\n const results = await lookup(host, { all: true });\n if (results.some((r) => isPrivateAddress(r.address))) return { allow: false, reason: \"resolves to a private address\" };\n } catch {\n return { allow: false, reason: \"DNS lookup failed\" };\n }\n }\n }\n return { allow: true };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { fileURLToPath } from \"node:url\";\nimport { dirname, join } from \"node:path\";\nimport type { Browser, BrowserContext } from \"playwright-core\";\nimport type { DataSource, ReportData, ReportTemplate, Theme } from \"@broadpaper/core\";\nimport { producerString, resolveLicenseStatus, watermarkFor, type LicenseStatus } from \"@broadpaper/license\";\nimport { decideRequest, type NetworkPolicy } from \"./ssrf.js\";\nimport { stampWatermark } from \"./watermark.js\";\nimport type { RuntimeRenderOutput } from \"../runtime/index.js\";\n\nexport interface PdfMetadata {\n title?: string;\n author?: string;\n subject?: string;\n keywords?: string[];\n /** Creation date. Defaults to `now`. */\n creationDate?: Date;\n}\n\nexport interface RenderPdfOptions {\n template: ReportTemplate | { schemaVersion: number; [k: string]: unknown };\n data?: ReportData;\n theme?: Partial<Theme>;\n dataSources?: DataSource[];\n /** Fixed clock for deterministic output. */\n now?: Date;\n locale?: string;\n currency?: string;\n timeZone?: string;\n metadata?: PdfMetadata;\n /**\n * JavaScript source for a browser bundle that registers custom blocks:\n * it must call `BroadPaper.registerBlocks([...])`. Built by the host with its\n * own bundler from `@broadpaper/core` block definitions.\n */\n customBlocksScript?: string;\n network?: NetworkPolicy;\n /** Per-render timeout in ms. Default 60000. */\n timeoutMs?: number;\n /** Refuse documents longer than this. Default 500. */\n maxPages?: number;\n /** Chromium tagged (accessible) PDF. Default true. */\n tagged?: boolean;\n /** PDF/A-like outline generation from headings. Default true. */\n outline?: boolean;\n /** Attach the runtime from a custom path (testing). */\n runtimePath?: string;\n /**\n * A licence for this render only, overriding whatever `configure` was given.\n * A service rendering for one organisation should configure once at startup\n * instead; this is for a host that renders on behalf of several.\n */\n license?: string | null;\n}\n\nexport interface RenderPdfResult {\n pdf: Buffer;\n pages: number;\n warnings: RuntimeRenderOutput[\"warnings\"];\n /** Wall-clock render time in ms. */\n durationMs: number;\n}\n\nexport class PdfRenderError extends Error {\n constructor(\n message: string,\n public readonly code: \"TIMEOUT\" | \"TOO_MANY_PAGES\" | \"RUNTIME\" | \"BROWSER\"\n ) {\n super(message);\n this.name = \"PdfRenderError\";\n }\n}\n\nlet runtimeCache: string | null = null;\n\nasync function loadRuntime(path?: string): Promise<string> {\n if (path) return readFile(path, \"utf8\");\n if (runtimeCache) return runtimeCache;\n const here = dirname(fileURLToPath(import.meta.url));\n const candidates = [join(here, \"runtime.global.js\"), join(here, \"..\", \"dist\", \"runtime.global.js\")];\n for (const c of candidates) {\n try {\n runtimeCache = await readFile(c, \"utf8\");\n return runtimeCache;\n } catch {\n /* try next */\n }\n }\n throw new PdfRenderError(\"BroadPaper runtime bundle not found. Run `pnpm --filter @broadpaper/pdf build`.\", \"RUNTIME\");\n}\n\nconst BLANK_HTML = `<!doctype html><html><head><meta charset=\"utf-8\"><title>BroadPaper</title></head><body></body></html>`;\n\n/**\n * A reusable PDF renderer bound to a Playwright browser. Each render uses a\n * fresh, isolated browser context (no cookies, storage or cache shared between\n * documents) and a strict network policy.\n */\nexport class PdfRenderer {\n constructor(private readonly browser: Browser) {}\n\n async render(opts: RenderPdfOptions): Promise<RenderPdfResult> {\n const started = Date.now();\n const timeout = opts.timeoutMs ?? 60_000;\n const runtime = await loadRuntime(opts.runtimePath);\n let context: BrowserContext | null = null;\n try {\n context = await this.browser.newContext({ javaScriptEnabled: true, offline: false, viewport: { width: 1200, height: 1600 }, deviceScaleFactor: 1, bypassCSP: false, locale: opts.locale ?? \"en-GB\", timezoneId: opts.timeZone });\n context.setDefaultTimeout(timeout);\n const counter = { count: 0 };\n const policy: NetworkPolicy = { allowedHosts: [], blockPrivateNetworks: true, maxRequests: 200, ...(opts.network ?? {}) };\n await context.route(\"**/*\", async (route) => {\n const url = route.request().url();\n const decision = await decideRequest(url, policy, counter);\n if (decision.allow) await route.continue();\n else await route.abort(\"blockedbyclient\");\n });\n\n const page = await context.newPage();\n const errors: string[] = [];\n page.on(\"pageerror\", (e) => errors.push(String(e)));\n await page.setContent(BLANK_HTML, { waitUntil: \"load\" });\n await page.addScriptTag({ content: runtime });\n if (opts.customBlocksScript) await page.addScriptTag({ content: opts.customBlocksScript });\n\n const input = {\n template: opts.template,\n data: opts.data ?? {},\n theme: opts.theme,\n dataSources: opts.dataSources ?? [],\n now: (opts.now ?? new Date()).toISOString(),\n locale: opts.locale,\n currency: opts.currency,\n timeZone: opts.timeZone,\n mode: \"preview\" as const\n };\n\n const result = (await Promise.race([\n page.evaluate(async (i) => window.BroadPaper.render(i as never), input),\n new Promise<never>((_, reject) => setTimeout(() => reject(new PdfRenderError(`Render timed out after ${timeout}ms`, \"TIMEOUT\")), timeout))\n ])) as RuntimeRenderOutput;\n\n if (errors.length) throw new PdfRenderError(`Runtime error: ${errors[0]}`, \"RUNTIME\");\n const maxPages = opts.maxPages ?? 500;\n if (result.pages > maxPages) throw new PdfRenderError(`Document has ${result.pages} pages, more than the limit of ${maxPages}`, \"TOO_MANY_PAGES\");\n\n await page.emulateMedia({ media: \"print\" });\n const pdf = await page.pdf({\n width: `${result.width}px`,\n height: `${result.height}px`,\n printBackground: true,\n preferCSSPageSize: true,\n margin: { top: 0, right: 0, bottom: 0, left: 0 },\n displayHeaderFooter: false,\n tagged: opts.tagged ?? true,\n outline: opts.outline ?? true\n });\n\n // The licence is checked here, on the way out, rather than inside the\n // page: nothing a host injects into the browser — a custom-blocks bundle,\n // its own runtime, its own CSS — sits between this and the file.\n const license = await resolveLicenseStatus(opts.license !== undefined ? { license: opts.license } : {});\n const finished = await applyMetadata(pdf, opts.metadata, opts.now, license);\n return { pdf: finished, pages: result.pages, warnings: result.warnings, durationMs: Date.now() - started };\n } catch (e) {\n if (e instanceof PdfRenderError) throw e;\n throw new PdfRenderError(`Browser failure: ${(e as Error).message}`, \"BROWSER\");\n } finally {\n await context?.close().catch(() => undefined);\n }\n }\n}\n\n/**\n * Writes document metadata (Title, Author, Subject, Keywords, Producer, dates)\n * into the PDF using pdf-lib, and stamps the evaluation mark when the licence\n * calls for one. With a fixed `now` the output is byte-stable.\n *\n * The two jobs are together because this is the last time the file is open:\n * every Chromium render ends here, so a PDF that leaves this function clean was\n * produced under a licence that says it may be.\n *\n * `license` is resolved from the configured licence when it is not supplied,\n * which keeps the guarantee for a caller reaching this function directly.\n */\nexport async function applyMetadata(pdf: Buffer, meta: PdfMetadata | undefined, now?: Date, license?: LicenseStatus): Promise<Buffer> {\n const { PDFDocument } = await import(\"pdf-lib\");\n const status = license ?? (await resolveLicenseStatus());\n const doc = await PDFDocument.load(pdf, { updateMetadata: false });\n const when = meta?.creationDate ?? now ?? new Date();\n const mark = watermarkFor(status);\n if (mark) await stampWatermark(doc, mark);\n doc.setProducer(producerString(status));\n doc.setCreator(\"BroadPaper\");\n doc.setCreationDate(when);\n doc.setModificationDate(when);\n if (meta?.title) doc.setTitle(meta.title, { showInWindowTitleBar: true });\n if (meta?.author) doc.setAuthor(meta.author);\n if (meta?.subject) doc.setSubject(meta.subject);\n if (meta?.keywords?.length) doc.setKeywords(meta.keywords);\n const bytes = await doc.save({ useObjectStreams: true, addDefaultPage: false });\n return Buffer.from(bytes);\n}\n\nexport interface BrowserFactory {\n launch(): Promise<Browser>;\n}\n\n/**\n * Convenience: renders one PDF with a temporary browser. For servers use\n * `PdfRenderer` with a long-lived browser instead.\n */\nexport async function renderPdf(opts: RenderPdfOptions & { browser?: Browser; launch?: () => Promise<Browser> }): Promise<RenderPdfResult> {\n let browser = opts.browser;\n let own = false;\n if (!browser) {\n const launch = opts.launch ?? defaultLaunch;\n browser = await launch();\n own = true;\n }\n try {\n return await new PdfRenderer(browser).render(opts);\n } finally {\n if (own) await browser.close().catch(() => undefined);\n }\n}\n\nexport async function defaultLaunch(): Promise<Browser> {\n // Playwright is an optional peer dependency: this package is the fidelity\n // reference rather than the recommended backend, and most hosts render with\n // Forme and never launch a browser at all. Neither driver being installed is\n // therefore an ordinary configuration and not a broken install, so it has to\n // say so — the bare module resolution error names a package the host never\n // knowingly asked for.\n let mod: typeof import(\"playwright-core\");\n try {\n mod = (await import(\"playwright\").catch(() => import(\"playwright-core\"))) as typeof import(\"playwright-core\");\n } catch {\n throw new PdfRenderError(\n \"The Chromium backend needs Playwright, an optional peer dependency of @broadpaper/pdf. Install playwright (or playwright-core, if you supply your own browser), or render with @broadpaper/forme, which needs no browser at all.\",\n \"BROWSER\"\n );\n }\n return mod.chromium.launch({ headless: true, args: [\"--disable-gpu\", \"--font-render-hinting=none\", \"--disable-dev-shm-usage\"] });\n}\n","/**\n * The evaluation mark, drawn into a finished PDF.\n *\n * The browserless backend hands the engine a watermark node and lets it draw;\n * Chromium has no such notion, so the mark goes on afterwards, into the file.\n * That is deliberately the *last* thing that happens to a PDF here rather than\n * a stylesheet injected into the page: a host supplying its own custom-blocks\n * bundle, its own CSS or its own runtime can change what the page looks like,\n * and none of it can change what comes out of this function.\n *\n * One line per page, centred, rotated, at the same colour and opacity the\n * engine uses, so an evaluation PDF looks the same whichever backend produced\n * it.\n */\nimport type { PDFDocument } from \"pdf-lib\";\nimport type { WatermarkSpec } from \"@broadpaper/license\";\n\nexport async function stampWatermark(doc: PDFDocument, spec: WatermarkSpec): Promise<void> {\n const { StandardFonts, degrees, rgb } = await import(\"pdf-lib\");\n // Helvetica-Bold is one of the fourteen faces every PDF reader has, so the\n // mark needs no embedded font and adds nothing to the file size.\n const font = await doc.embedFont(StandardFonts.HelveticaBold);\n const color = hexToRgb(spec.color);\n const radians = (spec.angle * Math.PI) / 180;\n const width = font.widthOfTextAtSize(spec.text, spec.fontSize);\n const height = font.heightAtSize(spec.fontSize);\n\n for (const page of doc.getPages()) {\n const { width: pw, height: ph } = page.getSize();\n // drawText places the baseline at (x, y) and then rotates about that point,\n // so the centring has to be done in the rotated frame: walk back along the\n // text's own axis by half its length, and off it by half its height.\n const x = pw / 2 - (Math.cos(radians) * width) / 2 + (Math.sin(radians) * height) / 2;\n const y = ph / 2 - (Math.sin(radians) * width) / 2 - (Math.cos(radians) * height) / 2;\n page.drawText(spec.text, {\n x,\n y,\n size: spec.fontSize,\n font,\n color: rgb(color.r, color.g, color.b),\n opacity: spec.opacity,\n rotate: degrees(spec.angle)\n });\n }\n}\n\nfunction hexToRgb(hex: string): { r: number; g: number; b: number } {\n const m = /^#?([0-9a-f]{6})$/i.exec(hex.trim());\n /* c8 ignore next -- the spec's colour is a constant; this guards a host that edited it */\n if (!m) return { r: 0.78, g: 0.06, b: 0.18 };\n const n = parseInt(m[1]!, 16);\n return { r: ((n >> 16) & 255) / 255, g: ((n >> 8) & 255) / 255, b: (n & 255) / 255 };\n}\n","import { createServer, type IncomingMessage, type Server, type ServerResponse } from \"node:http\";\nimport type { Browser } from \"playwright-core\";\nimport { PdfRenderer, PdfRenderError, defaultLaunch, type RenderPdfOptions } from \"./render-pdf.js\";\nimport type { NetworkPolicy } from \"./ssrf.js\";\n\nexport interface PdfServerOptions {\n port?: number;\n host?: string;\n /** Shared-secret bearer token. Strongly recommended outside of local development. */\n token?: string;\n /** Maximum request body size in bytes. Default 25 MB. */\n maxBodyBytes?: number;\n /** Concurrent renders. Default 4. */\n concurrency?: number;\n /** Default network policy (request body may narrow but never widen it). */\n network?: NetworkPolicy;\n /** Custom blocks bundle (JS source) injected into every render. */\n customBlocksScript?: string;\n launch?: () => Promise<Browser>;\n timeoutMs?: number;\n maxPages?: number;\n log?: (msg: string) => void;\n}\n\nexport interface PdfServer {\n server: Server;\n port: number;\n close(): Promise<void>;\n}\n\ninterface RenderRequestBody extends Omit<RenderPdfOptions, \"now\" | \"network\" | \"customBlocksScript\" | \"runtimePath\" | \"metadata\"> {\n now?: string;\n network?: { allowedHosts?: string[] };\n metadata?: { title?: string; author?: string; subject?: string; keywords?: string[] };\n /** \"pdf\" (default) returns application/pdf; \"json\" returns { pdfBase64, pages, warnings }. */\n format?: \"pdf\" | \"json\";\n}\n\nfunction readJson(req: IncomingMessage, limit: number): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n let size = 0;\n req.on(\"data\", (c: Buffer) => {\n size += c.length;\n if (size > limit) {\n reject(new Error(\"Request body too large\"));\n req.destroy();\n return;\n }\n chunks.push(c);\n });\n req.on(\"end\", () => {\n try {\n resolve(JSON.parse(Buffer.concat(chunks).toString(\"utf8\")));\n } catch {\n reject(new Error(\"Invalid JSON\"));\n }\n });\n req.on(\"error\", reject);\n });\n}\n\nfunction send(res: ServerResponse, status: number, body: unknown, headers: Record<string, string> = {}) {\n const json = JSON.stringify(body);\n res.writeHead(status, { \"content-type\": \"application/json; charset=utf-8\", \"content-length\": Buffer.byteLength(json), ...headers });\n res.end(json);\n}\n\n/**\n * Starts a small, dependency-free HTTP service:\n * POST /render → PDF bytes (or JSON with format: \"json\")\n * GET /health → { ok, browser }\n *\n * Deploy it next to your application. Report data never leaves your network.\n */\nexport async function createPdfServer(opts: PdfServerOptions = {}): Promise<PdfServer> {\n const log = opts.log ?? (() => undefined);\n const browser = await (opts.launch ?? defaultLaunch)();\n const renderer = new PdfRenderer(browser);\n const concurrency = opts.concurrency ?? 4;\n let active = 0;\n const queue: Array<() => void> = [];\n const acquire = () =>\n new Promise<void>((resolve) => {\n if (active < concurrency) {\n active++;\n resolve();\n } else queue.push(resolve);\n });\n const release = () => {\n active--;\n const next = queue.shift();\n if (next) {\n active++;\n next();\n }\n };\n\n const server = createServer(async (req, res) => {\n const url = new URL(req.url ?? \"/\", \"http://localhost\");\n res.setHeader(\"x-content-type-options\", \"nosniff\");\n if (req.method === \"GET\" && url.pathname === \"/health\") return send(res, 200, { ok: true, browser: browser.isConnected(), active, queued: queue.length });\n if (req.method === \"OPTIONS\") {\n res.writeHead(204, { \"access-control-allow-origin\": \"*\", \"access-control-allow-headers\": \"authorization, content-type\", \"access-control-allow-methods\": \"POST, GET, OPTIONS\" });\n return res.end();\n }\n if (req.method !== \"POST\" || url.pathname !== \"/render\") return send(res, 404, { error: \"Not found\" });\n if (opts.token) {\n const auth = req.headers.authorization ?? \"\";\n if (auth !== `Bearer ${opts.token}`) return send(res, 401, { error: \"Unauthorised\" });\n }\n let body: RenderRequestBody;\n try {\n body = (await readJson(req, opts.maxBodyBytes ?? 25 * 1024 * 1024)) as RenderRequestBody;\n } catch (e) {\n return send(res, 400, { error: (e as Error).message });\n }\n if (!body || typeof body !== \"object\" || !body.template) return send(res, 400, { error: \"Missing template\" });\n\n // Narrow the network policy: request may only restrict, never widen.\n const serverHosts = opts.network?.allowedHosts ?? [];\n const requested = body.network?.allowedHosts;\n const allowedHosts = requested ? requested.filter((h) => serverHosts.includes(\"*\") || serverHosts.includes(h)) : serverHosts;\n\n await acquire();\n const started = Date.now();\n try {\n const result = await renderer.render({\n template: body.template,\n data: body.data,\n theme: body.theme,\n dataSources: body.dataSources,\n now: body.now ? new Date(body.now) : undefined,\n locale: body.locale,\n currency: body.currency,\n timeZone: body.timeZone,\n metadata: body.metadata,\n network: { ...(opts.network ?? {}), allowedHosts },\n customBlocksScript: opts.customBlocksScript,\n timeoutMs: opts.timeoutMs,\n maxPages: opts.maxPages\n });\n log(`render ok pages=${result.pages} ms=${result.durationMs}`);\n res.setHeader(\"access-control-allow-origin\", \"*\");\n if (body.format === \"json\") return send(res, 200, { pdfBase64: result.pdf.toString(\"base64\"), pages: result.pages, warnings: result.warnings, durationMs: result.durationMs });\n res.writeHead(200, { \"content-type\": \"application/pdf\", \"content-length\": result.pdf.length, \"x-broadpaper-pages\": String(result.pages), \"x-broadpaper-warnings\": String(result.warnings.length), \"content-disposition\": `inline; filename=\"${(body.metadata?.title ?? \"report\").replace(/[^\\w.-]+/g, \"_\")}.pdf\"` });\n res.end(result.pdf);\n } catch (e) {\n const err = e as PdfRenderError;\n log(`render failed ${err.code ?? \"\"} ${err.message} ms=${Date.now() - started}`);\n const status = err instanceof PdfRenderError ? (err.code === \"TIMEOUT\" ? 504 : err.code === \"TOO_MANY_PAGES\" ? 413 : 500) : 500;\n res.setHeader(\"access-control-allow-origin\", \"*\");\n send(res, status, { error: err.message, code: err.code ?? \"UNKNOWN\" });\n } finally {\n release();\n }\n });\n\n const port = opts.port ?? 4780;\n await new Promise<void>((resolve) => server.listen(port, opts.host ?? \"0.0.0.0\", resolve));\n const address = server.address();\n const actualPort = typeof address === \"object\" && address ? address.port : port;\n log(`BroadPaper PDF service listening on http://${opts.host ?? \"0.0.0.0\"}:${actualPort}`);\n return {\n server,\n port: actualPort,\n close: async () => {\n await new Promise<void>((resolve) => server.close(() => resolve()));\n await browser.close().catch(() => undefined);\n }\n };\n}\n"],"mappings":"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","names":["i","G","mod"]}