@embedpdf/engine-core 3.0.0-next.13 → 3.0.0-next.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AbortError-DHqPBnYc.js → AbortError-DwuHPK_I.js} +2 -2
- package/dist/{AbortError-DHqPBnYc.js.map → AbortError-DwuHPK_I.js.map} +1 -1
- package/dist/{AbortError-Cq2igpZ6.cjs → AbortError-P0RU0Mgg.cjs} +4 -4
- package/dist/{AbortError-Cq2igpZ6.cjs.map → AbortError-P0RU0Mgg.cjs.map} +1 -1
- package/dist/{AnnotationListSnapshot-D3mFut1e.d.cts → AnnotationListSnapshot-D9R5n2Kf.d.cts} +237 -7
- package/dist/{AnnotationListSnapshot-D3mFut1e.d.ts → AnnotationListSnapshot-D9R5n2Kf.d.ts} +237 -7
- package/dist/{DocumentSecurityService-ClTZc0zO.d.cts → DocumentSecurityService-CIx1MT0T.d.cts} +2 -2
- package/dist/{DocumentSecurityService-_JRjqvoI.d.ts → DocumentSecurityService-Ca6EK3-3.d.ts} +2 -2
- package/dist/{Engine-Bx0NOfmd.d.cts → Engine-EWWHhEIi.d.ts} +17 -4
- package/dist/{Engine-DxtpCYcP.d.ts → Engine-FNaAEjfb.d.cts} +17 -4
- package/dist/conformance.cjs +382 -95
- package/dist/conformance.cjs.map +1 -1
- package/dist/conformance.d.cts +7 -3
- package/dist/conformance.d.ts +7 -3
- package/dist/conformance.js +302 -16
- package/dist/conformance.js.map +1 -1
- package/dist/derive-BbsDk_Kz.cjs +880 -0
- package/dist/derive-BbsDk_Kz.cjs.map +1 -0
- package/dist/derive-DAFJolWu.js +647 -0
- package/dist/derive-DAFJolWu.js.map +1 -0
- package/dist/{PageInsertBlankInput-cHq9-i-z.js → format-Bbphf4zR.js} +59 -2
- package/dist/format-Bbphf4zR.js.map +1 -0
- package/dist/{PageInsertBlankInput-CqXBmFhN.cjs → format-D_epWlob.cjs} +70 -1
- package/dist/format-D_epWlob.cjs.map +1 -0
- package/dist/index.cjs +127 -107
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +4 -4
- package/dist/runtime.cjs +137 -117
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.cts +29 -5
- package/dist/runtime.d.ts +29 -5
- package/dist/runtime.js +5 -5
- package/dist/{schemas-BLARNCgx.js → schemas-CFQGvWiu.js} +134 -4
- package/dist/schemas-CFQGvWiu.js.map +1 -0
- package/dist/{schemas-DIqFMmrC.cjs → schemas-D0g6tKa9.cjs} +250 -24
- package/dist/schemas-D0g6tKa9.cjs.map +1 -0
- package/dist/{builders-Bqm8yTpi.cjs → viewport-BWeNHZmb.cjs} +71 -132
- package/dist/viewport-BWeNHZmb.cjs.map +1 -0
- package/dist/{builders-Dqo2X-dt.js → viewport-CvMcadfQ.js} +39 -88
- package/dist/viewport-CvMcadfQ.js.map +1 -0
- package/dist/wire.cjs +25 -2
- package/dist/wire.cjs.map +1 -1
- package/dist/wire.d.cts +2739 -8
- package/dist/wire.d.ts +2739 -8
- package/dist/wire.js +10 -3
- package/dist/wire.js.map +1 -1
- package/package.json +1 -1
- package/dist/PageInsertBlankInput-CqXBmFhN.cjs.map +0 -1
- package/dist/PageInsertBlankInput-cHq9-i-z.js.map +0 -1
- package/dist/builders-Bqm8yTpi.cjs.map +0 -1
- package/dist/builders-Dqo2X-dt.js.map +0 -1
- package/dist/fold-2V29cxCV.cjs +0 -447
- package/dist/fold-2V29cxCV.cjs.map +0 -1
- package/dist/fold-CdEJTBTn.js +0 -334
- package/dist/fold-CdEJTBTn.js.map +0 -1
- package/dist/schemas-BLARNCgx.js.map +0 -1
- package/dist/schemas-DIqFMmrC.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewport-CvMcadfQ.js","names":[],"sources":["../src/dto/PdfAction.ts","../src/dto/PageRender.ts","../src/dto/PdfSaveMode.ts","../src/dto/RichText.ts","../src/identity/PageObjectNumber.ts","../src/identity/AnnotationStableId.ts","../src/revision/RevisionToken.ts","../src/revision/WeakAnnotationState.ts","../src/annotation/primitives.ts","../src/resource/BinarySource.ts","../src/resource/binaryMetadata.ts","../src/annotation/kinds/file-attachment/normalize.ts","../src/annotation/kinds/stamp/normalize.ts","../src/annotation/normalize.ts","../src/annotation/comments.ts","../src/mutation/AnnotationMutationImpactPolicy.ts","../src/annotation/appearance.ts","../src/identity/FormFieldRef.ts","../src/signature/analysis/pdf-value.ts","../src/signature/analysis/verdict.ts","../src/signature/analysis/evaluate.ts","../src/signature/analysis/restrictions.ts","../src/signature/analysis/resolve.ts","../src/search/literal.ts","../src/search/regex.ts","../src/search/matcher.ts","../src/search/snippet.ts","../src/text/layout.ts","../src/search/rects.ts","../src/search/epoch.ts","../src/auth/scope/pdf-bits.ts","../src/auth/scope/builders.ts","../src/measure/viewport.ts"],"sourcesContent":["import type { PdfDestination } from './PdfDestination';\n\n/** Normalized values of an action dictionary's `/S` name. */\nexport type PdfActionType = PdfActionNode['type'];\n\n/**\n * One Hide `/T` or ResetForm `/Fields` entry. Deliberately UNSCOPED: a\n * dictionary reference carries no page, so resolution (a name to widgets, an\n * object number to an annotation or field) is the interpreter's job — never\n * the extractor's.\n */\nexport type PdfActionTargetRef =\n | { kind: 'name'; name: string }\n | { kind: 'objectNumber'; objectNumber: number };\n\n/**\n * Decoded SubmitForm `/Flags` word (ISO 32000-2:2020 Table 240) plus the raw\n * value. `exclude` is DERIVED from bit 1 — never stored separately, so the\n * two cannot disagree. Note the two easily-missed positions verified against\n * the spec: bit 12 is `ExclFKey` (not \"ExclFDFTemplate\") and bit 13 is\n * reserved/undefined, so `EmbedForm` is bit 14.\n */\nexport interface SubmitFormFlags {\n raw: number;\n /** Bit 1: set → `fields` lists EXCLUDED fields. */\n exclude: boolean;\n /** Bit 2: submit designated valueless fields too, as name-only entries. */\n includeNoValueFields: boolean;\n /** Bits 3/6/9 folded into one verdict: bit 9 SubmitPDF dominates (\"all\n * other flags shall be ignored except GetMethod\"), else bit 6 XFDF, else\n * bit 3 HTML Form format, else FDF (the Table 240 default). */\n format: 'fdf' | 'html' | 'xfdf' | 'pdf';\n /** Bit 4. ISO makes GetMethod meaningful only with ExportFormat set, and\n * the bit-9 rule keeps it alive for SubmitPDF — so `'get'` only for\n * `'html'` and `'pdf'`; everything else posts. */\n method: 'post' | 'get';\n /** Bit 5 (meaningful only with ExportFormat; passed through — this stack\n * does not capture click coordinates). */\n submitCoordinates: boolean;\n /** Bit 7 (FDF only): include incremental updates via FDF `Differences`. */\n includeAppendSaves: boolean;\n /** Bit 8 (FDF only): include markup annotations. */\n includeAnnotations: boolean;\n /** Bit 10: convert date-like values to the standard date format. */\n canonicalFormat: boolean;\n /** Bit 11 (FDF, with IncludeAnnotations): only the current user's\n * annotations. */\n exclNonUserAnnots: boolean;\n /** Bit 12: the submitted FDF excludes its `F` entry. */\n exclFKey: boolean;\n /** Bit 14 (bit 13 is reserved): the FDF `F` entry embeds the source PDF. */\n embedForm: boolean;\n}\n\n/**\n * The one Table-240 decode, shared by the reader, the schema's producers,\n * and tests — so bit semantics cannot fork.\n */\nexport const decodeSubmitFormFlags = (raw: number): SubmitFormFlags => {\n const bit = (n: number): boolean => (raw & (1 << (n - 1))) !== 0;\n const format = bit(9) ? 'pdf' : bit(6) ? 'xfdf' : bit(3) ? 'html' : 'fdf';\n return {\n raw,\n exclude: bit(1),\n includeNoValueFields: bit(2),\n format,\n method: bit(4) && (format === 'html' || format === 'pdf') ? 'get' : 'post',\n submitCoordinates: bit(5),\n includeAppendSaves: bit(7),\n includeAnnotations: bit(8),\n canonicalFormat: bit(10),\n exclNonUserAnnots: bit(11),\n exclFKey: bit(12),\n embedForm: bit(14),\n };\n};\n\n/**\n * SubmitForm's extracted intent. ATOMIC on purpose: either every required\n * component resolved (a complete, executable payload) or the node carries no\n * payload at all — partial states are unrepresentable. An unreadable\n * REQUIRED component (`/F`) degrades the whole node to `unknown` +\n * `payload-dropped` at read time instead.\n */\nexport interface SubmitFormPayload {\n /** Resolved `/F` URL — a `<< /FS /URL >>` file specification (7.11.5,\n * `/UF` preferred over `/F` per 7.11.2); a bare string `/F` is accepted\n * as a producer-compat extension. */\n url: string;\n /**\n * `null` = `/Fields` ABSENT → Include/Exclude is ignored and every field\n * except NoExport-flagged ones is submitted (Table 239). `[]` =\n * present-but-empty: include mode submits NOTHING, exclude mode submits\n * everything eligible — presence and emptiness are different states.\n */\n fields: PdfActionTargetRef[] | null;\n flags: SubmitFormFlags;\n /** `/CharSet` (PDF 2.0), extracted but not encoded by this stack. */\n charSet?: string;\n}\n\ninterface PdfActionNodeCommon {\n /** Raw `/S` name, retained for unknown and future action types. */\n subtype: string;\n /** Normalized `/Next` children in PDF order. */\n next: PdfActionNode[];\n}\n\n/**\n * One detached node in a normalized PDF action tree, discriminated on the\n * interpreter that would execute it. Every executable arm carries its full\n * payload — a `goto` without a destination or a `uri` without a URI is\n * unrepresentable. A payload the reader cannot materialize degrades the node\n * to `unknown` (original `/S` kept on `subtype`) and appends the tree-level\n * `'payload-dropped'` warning.\n */\nexport type PdfActionNode = PdfActionNodeCommon &\n (\n | { type: 'javascript'; script: string }\n | { type: 'goto'; destination: PdfDestination }\n | { type: 'uri'; uri: string; isMap: boolean }\n | { type: 'named'; name: string }\n | { type: 'hide'; targets: PdfActionTargetRef[]; hide: boolean }\n | {\n type: 'reset-form';\n /**\n * `null` = `/Fields` ABSENT → reset every field (`exclude` is\n * meaningless). `[]` = present-but-empty: with `exclude` false reset\n * NOTHING, with `exclude` true reset EVERYTHING — PDFium's executor\n * branches on presence first.\n */\n fields: PdfActionTargetRef[] | null;\n exclude: boolean;\n }\n /** Reported, never executed. */\n | { type: 'goto-remote'; filePath: string }\n | { type: 'goto-embedded'; filePath: string }\n | { type: 'launch'; filePath: string }\n /** ISO allows `/Rendition` to carry `/JS`; preserved, not collected. */\n | { type: 'rendition'; script?: string }\n /** Recognized; executable only when `payload` is present. Absent payload\n * = extracted by an older runtime (skew) — the node stays\n * recognized-inert exactly as before this payload existed. */\n | { type: 'submit-form'; payload?: SubmitFormPayload }\n | { type: 'thread' }\n | { type: 'sound' }\n | { type: 'movie' }\n | { type: 'import-data' }\n | { type: 'set-ocg-state' }\n | { type: 'transition' }\n | { type: 'goto-3d-view' }\n | { type: 'unknown' }\n );\n\nexport type PdfActionWarning =\n | 'cycle-dropped'\n | 'malformed-next'\n | 'incomplete'\n /** A node's payload could not be read; that node degraded to `unknown`. */\n | 'payload-dropped';\n\n/**\n * One extracted action root plus the native reader's safety verdict.\n * Consumers must never execute a tree whose `incomplete` flag is true.\n */\nexport interface PdfActionTree {\n /** Null when the model was valid but its root exceeded a safety bound. */\n root: PdfActionNode | null;\n incomplete: boolean;\n /** Raw native bits, retained so newer warnings survive older SDKs.\n * TS-detected warnings (`payload-dropped`) appear only in `warnings`. */\n warningFlags: number;\n warnings: PdfActionWarning[];\n}\n\nexport interface PdfFieldActions {\n keystroke?: PdfActionTree;\n format?: PdfActionTree;\n validate?: PdfActionTree;\n calculate?: PdfActionTree;\n}\n\nexport interface PdfPageActions {\n open?: PdfActionTree;\n close?: PdfActionTree;\n}\n\nexport interface PdfAnnotationActions {\n activate?: PdfActionTree;\n cursorEnter?: PdfActionTree;\n cursorExit?: PdfActionTree;\n mouseDown?: PdfActionTree;\n mouseUp?: PdfActionTree;\n focus?: PdfActionTree;\n blur?: PdfActionTree;\n pageOpen?: PdfActionTree;\n pageClose?: PdfActionTree;\n pageVisible?: PdfActionTree;\n pageInvisible?: PdfActionTree;\n}\n\nexport interface NamedJavaScriptAction {\n /** Name-tree key. Array order is the PDF boot order. */\n name: string;\n action: PdfActionTree;\n}\n\n/** Catalog-owned actions. Page actions stay on their owning PageLayout. */\nexport interface DocumentActionsSnapshot {\n nameTreeScripts: NamedJavaScriptAction[];\n /** Action-form `/OpenAction`. Mutually exclusive with `openDestination` —\n * `/OpenAction` is one entry, a dictionary or an array. */\n openAction: PdfActionTree | null;\n /** Destination-form `/OpenAction` — the initial view, not an action.\n * Optional on the wire for skew tolerance (absent ≡ null); the schema\n * defaults it, so parsed snapshots always carry the key. */\n openDestination?: PdfDestination | null;\n willClose?: PdfActionTree;\n willSave?: PdfActionTree;\n didSave?: PdfActionTree;\n willPrint?: PdfActionTree;\n didPrint?: PdfActionTree;\n}\n\n/**\n * Aggregate guard applied across every action model read by one job. Native\n * limits are per model; this prevents a document containing many models from\n * creating an unbounded detached snapshot.\n */\nexport interface ActionReadBudget {\n maxModels: number;\n maxNodes: number;\n maxScriptCodeUnits: number;\n /** Hide `/T` + ResetForm/SubmitForm `/Fields` entries, aggregate across\n * the job. */\n maxTargetEntries: number;\n /** Payload string code units (URIs, submit URLs/CharSets, names, file\n * paths, name-tree script names), aggregate across the job. Reserved\n * BEFORE allocation. */\n maxPayloadCodeUnits: number;\n}\n","import { EngineError } from '../errors/EngineError';\nimport { EngineErrorCode } from '../errors/EngineErrorCode';\nimport type { PdfRect, PdfRotation } from '../geometry/primitives';\n\nexport type PageRenderEncodedFormat = 'png' | 'webp' | 'bmp';\n\n/**\n * Formats that are acceptable for cacheable cloud HTTP render endpoints.\n * BMP and raw RGBA stay local-only because they are intentionally huge.\n */\nexport type PageNetworkRenderFormat = 'png' | 'webp';\n\nexport type PageRenderFormat = PageRenderEncodedFormat | 'rgba';\n\nexport type PageRenderBackground = 'white' | 'transparent';\n\nexport type PageRenderViewport =\n | {\n /**\n * Render one PDF user-space unit as `scale` device pixels. Callers\n * that care about devicePixelRatio should fold it into this value.\n */\n kind: 'scale';\n scale?: number;\n }\n | {\n /**\n * Exact output width in device pixels. Height preserves the region's\n * aspect ratio after rotation.\n */\n kind: 'width';\n width: number;\n };\n\nexport type PageRenderTarget =\n | { kind: 'page' }\n | {\n kind: 'rect';\n /**\n * PDF user-space rectangle. Same convention as annotation rects:\n * top > bottom, origin at the PDF page's bottom-left.\n */\n rect: PdfRect;\n };\n\nexport interface PageRenderOptions {\n target?: PageRenderTarget;\n viewport?: PageRenderViewport;\n rotation?: PdfRotation;\n background?: PageRenderBackground;\n includeAnnotations?: boolean;\n /**\n * Output-pixel budget: the renderer rejects (InvalidArg) instead of\n * allocating when `outputWidth × outputHeight` exceeds it. A WIDTH\n * lattice bounds width but not height — a 1×14,400pt page still\n * explodes vertically — so the guard lives where the allocation\n * happens (the decode-bomb-guard pattern). SERVER requests carry it\n * from the deployment's render policy; LOCAL engines inject it only\n * when `localEngine({ renderPolicy })` configured a budget — the\n * default local policy stays continuous and unbudgeted (exactness is\n * the local product promise).\n */\n maxOutputPixels?: number;\n}\n\nexport interface PageImageOptions extends PageRenderOptions {\n format?: PageRenderEncodedFormat;\n quality?: number;\n}\n\nexport interface PageRenderQuery {\n options: PageImageOptions;\n contentVersion?: number;\n annotationVersion?: number;\n}\n\n/**\n * Raw renderer output shared by local workers and server workers. The pixel\n * buffer is a first-class ArrayBuffer so worker transports can transfer\n * ownership instead of cloning it.\n */\nexport interface PageRaster {\n width: number;\n height: number;\n stride: number;\n color: 'rgba8';\n premultipliedAlpha: false;\n data: ArrayBuffer;\n}\n\nexport interface PageImageResult {\n width?: number;\n height?: number;\n format: PageRenderEncodedFormat;\n contentType: string;\n source: PageImageSource;\n}\n\nexport type PageImageSource = { kind: 'bytes'; bytes: Uint8Array } | { kind: 'url'; url: string };\n\nexport interface PageImageObjectUrl {\n url: string;\n revoke(): void;\n}\n\nexport interface PageImageHandle extends PageImageResult {\n objectUrl(signal?: AbortSignal): Promise<PageImageObjectUrl>;\n}\n\nexport interface PageImageBlobSource {\n blob(signal?: AbortSignal): Promise<Blob>;\n}\n\nexport function createPageImageHandle(\n result: PageImageResult,\n blobSource: PageImageBlobSource,\n): PageImageHandle {\n return {\n ...result,\n async objectUrl(signal?: AbortSignal) {\n if (typeof Blob === 'undefined' || typeof URL === 'undefined' || !URL.createObjectURL) {\n throw new EngineError(\n EngineErrorCode.RuntimeUnavailable,\n 'Object URLs are not available in this environment',\n );\n }\n\n const blob = await blobSource.blob(signal);\n const url = URL.createObjectURL(blob);\n return { url, revoke: () => URL.revokeObjectURL(url) };\n },\n };\n}\n","export type PdfSaveMode = 'incremental' | 'rewrite';\n\nexport const DEFAULT_PDF_SAVE_MODE: PdfSaveMode = 'incremental';\n","import type { TextAlignment } from '../annotation/primitives';\n\n/**\n * Rich text of a FreeText annotation (`/RC` + `/DS`), the model the engine\n * lays out and writes. Runs carry only the style they override (deltas\n * against the body), exactly as the XHTML spans do, so changing the body\n * style moves every run that did not override that property.\n *\n * Families name faces the way a PDF does: a standard-14 family\n * (`\"Helvetica\"`), a font registered through `engine.fonts` (its family, or\n * its `key` — the engine resolves either), or a family already embedded in\n * the document. A family that resolves nowhere substitutes Helvetica; the\n * appearance still renders and the box still edits.\n */\nexport type RichTextDecoration = 'underline' | 'line-through' | 'word';\nexport type RichTextScript = 'normal' | 'sub' | 'super';\nexport type RichTextAlign = TextAlignment | 'justify';\nexport type RichTextDirection = 'ltr' | 'rtl';\n\nexport interface RichTextRunStyle {\n family: string;\n /** 100..900. */\n weight: number;\n italic: boolean;\n /** Points. */\n size: number;\n /** `#RRGGBB`. */\n color: string;\n decoration: RichTextDecoration[];\n script: RichTextScript;\n /** Points, added after every glyph. */\n letterSpacing: number;\n /** 1 = normal (`xfa-font-horizontal-scale` / 100). */\n horizontalScale: number;\n /** CSS declarations the engine does not model, kept verbatim. */\n unknown?: string;\n}\n\nexport interface RichTextMargins {\n top: number;\n bottom: number;\n left: number;\n right: number;\n}\n\nexport interface RichTextParagraphProps {\n align: RichTextAlign;\n dir: RichTextDirection;\n /** Points; absent = the normal line box. */\n lineHeight?: number;\n margins?: RichTextMargins;\n textIndent?: number;\n unknown?: string;\n}\n\nexport interface RichTextRun {\n /** May contain `\\r`: a hard line break inside the paragraph. */\n text: string;\n /** The properties this run overrides. Absent = the body style. */\n style?: Partial<RichTextRunStyle>;\n}\n\n/** A paragraph: its own alignment/direction when they differ from the body's. */\nexport interface RichTextParagraph extends Partial<RichTextParagraphProps> {\n runs: RichTextRun[];\n}\n\nexport type RichTextBody = RichTextRunStyle & RichTextParagraphProps;\n\n/** What an annotation reads back: a complete body, every paragraph resolved. */\nexport interface RichTextDocument {\n body: RichTextBody;\n paragraphs: RichTextParagraph[];\n}\n\n/**\n * What a draft or patch writes. `body` may be omitted (the annotation's\n * current body style stays — the \"plain text replacement\" of the patch\n * table) or partial (missing properties take the engine's defaults:\n * Helvetica 12 pt black, left-aligned, ltr).\n */\nexport interface RichTextDocumentInput {\n body?: Partial<RichTextBody>;\n paragraphs: RichTextParagraph[];\n}\n\n/** The plain-text projection of a rich document: paragraphs joined by `\\r`,\n * runs concatenated — what the engine writes to `/Contents`. */\nexport function richTextPlainText(doc: { paragraphs: readonly RichTextParagraph[] }): string {\n return doc.paragraphs.map((p) => p.runs.map((r) => r.text).join('')).join('\\r');\n}\n\n/** Plain text as rich paragraphs: one per line break, one run each, no\n * overrides (the engine's own `/Contents` fallback shape). */\nexport function richTextParagraphsFromPlainText(text: string): RichTextParagraph[] {\n return text.split(/\\r\\n|\\r|\\n/).map((line) => ({ runs: [{ text: line }] }));\n}\n","/**\n * PDF indirect object number for a page.\n *\n * Resolved via the PDFium runtime helper `EPDFPage_GetObjectNumber(pagePtr)`.\n * Always > 0 for well-formed PDFs. This replaces the v2 page index as the\n * primary addressing key. The page index is kept on `PageHandle` as display\n * metadata only, because it can shift when pages are inserted, deleted, or\n * reordered while a session is open.\n */\nexport type PageObjectNumber = number;\n\n/**\n * Type guard for the rare malformed-PDF case where a page is a direct\n * object. The engine treats `0` as malformed and throws `EngineError(NotFound)`\n * before any page-level operation.\n */\nexport function isValidPageObjectNumber(value: unknown): value is PageObjectNumber {\n return typeof value === 'number' && Number.isInteger(value) && value > 0;\n}\n","/**\n * The two durable ways to address an annotation across reads.\n *\n * `objectNumber` is the PDF indirect object number, returned by\n * `EPDFAnnot_GetObjectNumber(annotPtr)`. It is `> 0` for indirect objects\n * (the overwhelming common case) and `0` for direct objects (rare, legacy\n * PDFs). When the engine sees `0` it falls back to `nm` if present, or\n * promotes the annotation to a weak ref (`AnnotationRef.kind === 'index'`).\n *\n * `nm` is the value of the annotation's `/NM` entry. The v3 engine never\n * writes `/NM` on read — clients can opt into symbolic IDs by passing one to\n * `create()`, but reads never mutate the document.\n */\nexport type AnnotationStableId =\n | { kind: 'objectNumber'; value: number }\n | { kind: 'nm'; value: string };\n\n/**\n * URL-safe encoding of a stable id, used by the cloud HTTP surface as the\n * `:annotKey` route parameter. Decoded by the server back into an\n * `AnnotationStableId` via `decodeStableIdKey`.\n *\n * Format:\n * `{ kind: 'objectNumber', value: 42 }` -> `'obj:42'`\n * `{ kind: 'nm', value: 'foo bar' }` -> `'nm:foo bar'`\n *\n * The caller is responsible for `encodeURIComponent`-ing the result before\n * splicing it into a URL path; `wirePaths.layerAnnotationByKey` already does\n * that. /NM values are opaque strings and may contain anything; the\n * `nm:` prefix lets the decoder distinguish them from numeric ids\n * unambiguously.\n */\nexport function encodeStableIdKey(id: AnnotationStableId): string {\n if (id.kind === 'objectNumber') {\n if (!Number.isInteger(id.value) || id.value <= 0) {\n throw new RangeError(\n `encodeStableIdKey: objectNumber must be a positive integer, got ${id.value}`,\n );\n }\n return `obj:${id.value}`;\n }\n return `nm:${id.value}`;\n}\n\n/**\n * Inverse of `encodeStableIdKey`. Returns `null` for malformed input so\n * the server can answer 400 InvalidArg with a useful message instead of\n * throwing.\n *\n * The input is the already-`decodeURIComponent`-ed segment from the route\n * path. Empty `/NM` values are rejected: `nm:` with no suffix is not a\n * valid identity.\n */\nexport function decodeStableIdKey(key: string): AnnotationStableId | null {\n if (key.startsWith('obj:')) {\n const rest = key.slice('obj:'.length);\n const n = Number.parseInt(rest, 10);\n if (!Number.isInteger(n) || n <= 0 || String(n) !== rest) return null;\n return { kind: 'objectNumber', value: n };\n }\n if (key.startsWith('nm:')) {\n const value = key.slice('nm:'.length);\n if (value.length === 0) return null;\n return { kind: 'nm', value };\n }\n return null;\n}\n","import type { PageObjectNumber } from '../identity/PageObjectNumber';\n\n/**\n * Opaque token a client must hand back when addressing an annotation by\n * `(pageObjectNumber, index)`. The engine validates strict equality against\n * its own `RevisionStore`; mismatches throw `EngineError(InvalidReference)`.\n *\n * Bleed-over prevention: `docSessionId` ties a token to one open session,\n * so a token minted before close-and-reopen is rejected by the new session.\n */\nexport interface RevisionToken {\n docSessionId: string;\n pageObjectNumber: PageObjectNumber;\n generation: number;\n}\n\nexport function revisionTokensEqual(a: RevisionToken, b: RevisionToken): boolean {\n return (\n a.docSessionId === b.docSessionId &&\n a.pageObjectNumber === b.pageObjectNumber &&\n a.generation === b.generation\n );\n}\n","/**\n * Tri-state knowledge about weak annotation identities on a page.\n *\n * `known(false)` is a stronger claim than \"we have not looked yet\": it means\n * the page's annotations were scanned and every annotation had a durable\n * identity. Cloud/CDN manifests must only publish boolean weak flags from a\n * known state.\n */\nexport type WeakAnnotationState =\n | { kind: 'unknown' }\n | { kind: 'known'; hasAnyWeakAnnotations: boolean };\n\nexport const UNKNOWN_WEAK_ANNOTATION_STATE: WeakAnnotationState = { kind: 'unknown' };\n\nexport function knownWeakAnnotationState(hasAnyWeakAnnotations: boolean): WeakAnnotationState {\n return { kind: 'known', hasAnyWeakAnnotations };\n}\n","/**\n * Wire-stable annotation primitives that are NOT pure geometry.\n *\n * Geometry primitives (points, rects, sizes, quads, rotation) now live in\n * `../geometry` as the canonical `Pdf*` vocabulary. The aliases below are\n * TRANSITIONAL re-exports kept only so existing consumers keep compiling\n * during the geometry consolidation; new code should import `Pdf*` directly\n * from `../geometry`.\n *\n * These do not depend on PDFium or any browser/Node surface; they are\n * the lingua franca between local engine, cloud engine, and server.\n */\n\nimport type { PdfPoint, PdfRect, PdfRotation, PdfSize } from '../geometry/primitives';\n\n/** @deprecated Use `PdfPoint` from `../geometry`. */\nexport type Point = PdfPoint;\n/** @deprecated Use `PdfRect` from `../geometry`. */\nexport type Rect = PdfRect;\n/** @deprecated Use `PdfSize` from `../geometry`. */\nexport type Size = PdfSize;\n/** @deprecated Use `PdfRotation` from `../geometry`. */\nexport type Rotation = PdfRotation;\n\n/**\n * sRGB color. Components are 0..255 integers. Engines normalize PDFium's\n * device color space into sRGB at read time.\n *\n * Colour carries NO alpha: annotation transparency is a separate concern\n * stored in `/CA` and surfaced as the `opacity` style field, so there is a\n * single source of truth for transparency. See `ColorStyleFields.opacity`.\n */\nexport interface Color {\n r: number;\n g: number;\n b: number;\n}\n\n/**\n * /LE entries (line endings). Maps PDFium FPDFAnnot_GetLineEndings codes\n * onto the spec names. We use kebab-case so the wire format is stable\n * across language ports.\n */\nexport type LineEnding =\n | 'none'\n | 'square'\n | 'circle'\n | 'diamond'\n | 'open-arrow'\n | 'closed-arrow'\n | 'butt'\n | 'r-open-arrow'\n | 'r-closed-arrow'\n | 'slash';\n\n/**\n * The `/LE` pair carried by line and polyline annotations: the ending\n * drawn at the start point and the ending drawn at the end point.\n */\nexport interface LineEndings {\n start: LineEnding;\n end: LineEnding;\n}\n\n/**\n * The 14 standard PDF fonts a free-text annotation's `/DA` can name. We use\n * kebab-case so the wire format is stable across language ports; the engine\n * maps these onto PDFium's `FPDF_STANDARD_FONT` integer codes at write time.\n */\nexport type StandardFont =\n | 'courier'\n | 'courier-bold'\n | 'courier-bold-oblique'\n | 'courier-oblique'\n | 'helvetica'\n | 'helvetica-bold'\n | 'helvetica-bold-oblique'\n | 'helvetica-oblique'\n | 'times-roman'\n | 'times-bold'\n | 'times-bold-italic'\n | 'times-italic'\n | 'symbol'\n | 'zapf-dingbats';\n\n/**\n * Font selector for a free-text annotation: either one of the 14 PDF\n * {@link StandardFont} names, or the `key` of a font registered through\n * `engine.fonts` (local/WASM engine only).\n *\n * The `(string & {})` arm keeps the standard-font literals auto-completing\n * while still accepting any registered key. Because the standard names are\n * matched first at write time, those 14 names are reserved: don't register a\n * custom font under a key like `'helvetica'`.\n */\nexport type FreeTextFont = StandardFont | (string & {});\n\n/**\n * Horizontal text alignment (`/Q`) for free-text annotations. Maps onto the\n * ISO 32000 §12.7.3.3 quadding codes 0/1/2 at write time.\n */\nexport type TextAlignment = 'left' | 'center' | 'right';\n\n/**\n * Free-text `/IT` intent. `free-text` is a plain text box; `free-text-callout`\n * adds a `/CL` leader line pointing at the called-out region.\n */\nexport type FreeTextIntent = 'free-text' | 'free-text-callout';\n\n/** Caret `/IT` intent used by an Acrobat-compatible replace-text edit. */\nexport type CaretIntent = 'replace';\n\n/** Strikeout `/IT` intent used by the subordinate part of a replace-text edit. */\nexport type StrikeoutIntent = 'strikeout-text-edit';\n\n/** Ink `/IT` intent used by an Acrobat-compatible freehand highlighter. */\nexport type InkIntent = 'ink-highlight';\n\n/**\n * Effective blend mode of an annotation's normal appearance stream (`/AP /N`).\n * Values use CSS-compatible kebab-case so the wire vocabulary is portable; the\n * engine maps them onto PDFium's `FPDF_BLENDMODE` integer codes.\n */\nexport type BlendMode =\n | 'normal'\n | 'multiply'\n | 'screen'\n | 'overlay'\n | 'darken'\n | 'lighten'\n | 'color-dodge'\n | 'color-burn'\n | 'hard-light'\n | 'soft-light'\n | 'difference'\n | 'exclusion'\n | 'hue'\n | 'saturation'\n | 'color'\n | 'luminosity';\n\n/**\n * Border/line style for shape annotations — the `/BS /S` (border style)\n * subset PDFium can author. Maps onto the ISO 32000 §8.4.3.3 border style\n * names. Cloudy borders are a SEPARATE concern (`/BE` border effect),\n * surfaced as `cloudyIntensity` on the shape DTO, not as a border style.\n *\n * kebab-/lower-case so the wire format is stable across language ports;\n * the engine maps these onto PDFium's integer codes at write time.\n */\nexport type AnnotationBorderStyle = 'solid' | 'dashed' | 'beveled' | 'inset';\n\n/**\n * `/RD` (rectangle differences) for shape annotations — the four margins,\n * in PDF points, between the annotation `/Rect` and the geometry actually\n * drawn inside it. Used so a thick/cloudy border has room to render\n * without being clipped by the `/Rect`. y-up PDF user space, so each value\n * is a non-negative inset from the corresponding `/Rect` edge.\n */\nexport interface PdfRectDifferences {\n left: number;\n top: number;\n right: number;\n bottom: number;\n}\n\n/**\n * The `/RT` (reply type) relationship an annotation declares toward the\n * annotation its `/IRT` points at (ISO 32000 §12.5.6.2). Wire-stable\n * kebab/lower-case strings; the engine maps these onto PDFium's\n * `FPDF_ANNOT_REPLY_TYPE` integer codes at read/write time.\n *\n * 'reply' -> `/R` a comment-thread reply (the ISO default when\n * `/IRT` is present but `/RT` is absent).\n * 'group' -> `/Group` a subordinate part of one logical annotation\n * group (e.g. the Caret of a text-edit pair).\n */\nexport type AnnotationReplyType = 'reply' | 'group';\n\n/** The two ISO 32000 §12.5.6.3 standard state models (Table 174). */\nexport type KnownAnnotationStateModel = 'review' | 'marked';\n\n/**\n * The `/StateModel` of an annotation-state text annotation — ISO 32000\n * §12.5.6.3. The standard models are `'review'` and `'marked'`, but the\n * PDF stores the entry as a free text string and Acrobat supports\n * registering custom state models, so the type stays open. The\n * `(string & {})` arm keeps the standard literals auto-completing while\n * accepting any custom model (the {@link FreeTextFont} pattern).\n *\n * Known values are wire-stable lowercase; the engine maps them onto the\n * capitalized PDF spellings (`Review`, `Marked`) at read/write time.\n * Unknown values round-trip verbatim in both directions.\n */\nexport type AnnotationStateModel = KnownAnnotationStateModel | (string & {});\n\n/** The ISO 32000 §12.5.6.3 standard states (Table 174). */\nexport type KnownAnnotationState =\n | 'accepted'\n | 'rejected'\n | 'cancelled'\n | 'completed'\n | 'none'\n | 'marked'\n | 'unmarked';\n\n/**\n * The `/State` an annotation-state text annotation sets — ISO 32000\n * §12.5.6.3. `'accepted' | 'rejected' | 'cancelled' | 'completed' |\n * 'none'` belong to the `'review'` model; `'marked' | 'unmarked'` to the\n * `'marked'` model. Open for the same reason as\n * {@link AnnotationStateModel}: custom models bring custom states.\n *\n * States are PER USER and live on separate text annotations replying\n * (`/IRT`) to their target — never on the target itself. The `/T` of the\n * state annotation names who set it; later changes by the same user\n * chain as replies to their previous state annotation, latest wins.\n */\nexport type AnnotationState = KnownAnnotationState | (string & {});\n\n/**\n * Bitset wrapper for the `/F` (Annotation Flags) PDF entry. We expose each\n * bit as its own boolean so callers don't have to know the bit positions.\n */\nexport interface AnnotationFlags {\n invisible: boolean;\n hidden: boolean;\n print: boolean;\n noZoom: boolean;\n noRotate: boolean;\n noView: boolean;\n readOnly: boolean;\n locked: boolean;\n toggleNoView: boolean;\n lockedContents: boolean;\n}\n\nexport const NO_ANNOTATION_FLAGS: AnnotationFlags = {\n invisible: false,\n hidden: false,\n print: false,\n noZoom: false,\n noRotate: false,\n noView: false,\n readOnly: false,\n locked: false,\n toggleNoView: false,\n lockedContents: false,\n};\n","/**\n * Inline binary payloads for annotation drafts/patches.\n *\n * Public rule (see also `annotation/normalize.ts`): binary data is a call\n * ARGUMENT, never engine state. Callers put bytes directly on the draft\n * field that names their role (stamp `source`, future file-attachment\n * `file`); normalization replaces each such field with a `ResourceRef`\n * and moves the bytes into a `WireResourceMap` that travels out-of-band\n * (worker: transferable buffers; cloud: multipart parts). After the call,\n * the only durable home for the bytes is the PDF itself.\n */\n\n/**\n * Richest accepted input for a binary field. `mimeType` is advisory only —\n * every engine sniffs magic bytes and the sniffed format wins (the server\n * cannot trust a declared type anyway).\n */\nexport type BinarySource = Uint8Array | Blob | BinaryPayload;\n\nexport interface BinaryPayload {\n data: Uint8Array | Blob;\n /** Advisory only — engines always sniff magic bytes. */\n mimeType?: string;\n /** Optional display/file name (multipart `filename`, future /UF). */\n name?: string;\n}\n\n/**\n * A resolved binary payload in wire form: a PRIVATE COPY of the caller's\n * bytes, owned by the call and ready to ship (worker transfer list or\n * multipart part body). Ownership is the whole point: the local engine puts\n * `bytes` on a postMessage transfer list, which detaches the buffer, and a\n * `BinarySource` is a borrowed argument — never the caller's buffer to lose.\n * Blob sources yield fresh bytes by construction; Uint8Array sources are\n * copied here so a full-span view is not silently aliased and killed.\n */\nexport interface WireResource {\n bytes: ArrayBuffer;\n mimeType?: string;\n name?: string;\n}\n\n/** Keyed resources accompanying one mutation. Keys are allocator-generated (`r0`, `r1`, …). */\nexport type WireResourceMap = Record<string, WireResource>;\n\n/** What replaces a `BinarySource` field in the wire form of a draft/patch. */\nexport interface ResourceRef {\n resource: string;\n}\n\nfunction isBlob(value: unknown): value is Blob {\n return typeof Blob !== 'undefined' && value instanceof Blob;\n}\n\n/**\n * Copy a Uint8Array view into a fresh, exactly-sized ArrayBuffer the call\n * owns. Always copies — even when the view spans its whole buffer — because\n * the result may be transferred to a worker (detaching it), and the view is\n * the caller's. Returning `view.buffer` here would let one transfer zero\n * the caller's bytes (a stamp library's Uint8Array became single-use).\n * Callers wanting a zero-copy hand-off need an explicit \"give\" form, as\n * `pages.insert` has for bare ArrayBuffers; `BinarySource` has none.\n */\nfunction toOwnedArrayBuffer(view: Uint8Array): ArrayBuffer {\n const copy = new ArrayBuffer(view.byteLength);\n new Uint8Array(copy).set(view);\n return copy;\n}\n\n/**\n * Resolve any accepted `BinarySource` form into a `WireResource`.\n * Async because Blob bytes can only be read asynchronously.\n */\nexport async function resolveBinarySource(source: BinarySource): Promise<WireResource> {\n if (source instanceof Uint8Array) {\n return { bytes: toOwnedArrayBuffer(source) };\n }\n if (isBlob(source)) {\n const blobName = blobFileName(source);\n return {\n bytes: await source.arrayBuffer(),\n mimeType: source.type || undefined,\n ...(blobName !== undefined ? { name: blobName } : {}),\n };\n }\n const { data, mimeType, name } = source;\n const inner =\n data instanceof Uint8Array\n ? {\n bytes: toOwnedArrayBuffer(data),\n mimeType: undefined as string | undefined,\n name: undefined as string | undefined,\n }\n : {\n bytes: await data.arrayBuffer(),\n mimeType: data.type || undefined,\n name: blobFileName(data),\n };\n const resolvedName = name ?? inner.name;\n return {\n bytes: inner.bytes,\n ...((mimeType ?? inner.mimeType) ? { mimeType: mimeType ?? inner.mimeType } : {}),\n ...(resolvedName !== undefined ? { name: resolvedName } : {}),\n };\n}\n\n/** A browser `File` is a Blob with a `name` — pick it up so attachment\n * drafts can pass a `File` directly without repeating the file name. */\nfunction blobFileName(blob: Blob): string | undefined {\n const name = (blob as File).name;\n return typeof name === 'string' && name.length > 0 ? name : undefined;\n}\n","/**\n * Magic-byte format detection for inline binary payloads.\n *\n * Ported from v2 (`@embedpdf/models` image-metadata). Declared mime types\n * are never trusted — the sniffed format is canonical on every engine and\n * on the server. Raster formats include intrinsic pixel dimensions (used\n * for aspect-ratio fitting); PDF only identifies the format.\n */\n\nexport type BinaryMimeType = 'image/png' | 'image/jpeg' | 'application/pdf';\n\nexport type BinaryMetadata =\n | { mimeType: 'image/png'; width: number; height: number }\n | { mimeType: 'image/jpeg'; width: number; height: number }\n | { mimeType: 'application/pdf' };\n\n/**\n * Detect format (and intrinsic dimensions for rasters) of a binary buffer.\n *\n * @returns metadata, or `null` for unsupported/corrupt data\n */\nexport function sniffBinaryMetadata(buffer: ArrayBuffer): BinaryMetadata | null {\n if (buffer.byteLength < 4) return null;\n\n const bytes = new Uint8Array(buffer);\n\n if (bytes[0] === 0x89 && bytes[1] === 0x50 && bytes[2] === 0x4e && bytes[3] === 0x47) {\n return parsePng(buffer);\n }\n\n if (bytes[0] === 0xff && bytes[1] === 0xd8 && bytes[2] === 0xff) {\n return parseJpeg(buffer);\n }\n\n if (bytes[0] === 0x25 && bytes[1] === 0x50 && bytes[2] === 0x44 && bytes[3] === 0x46) {\n return { mimeType: 'application/pdf' };\n }\n\n return null;\n}\n\nfunction parsePng(buffer: ArrayBuffer): BinaryMetadata | null {\n if (buffer.byteLength < 24) return null;\n const view = new DataView(buffer);\n const width = view.getUint32(16);\n const height = view.getUint32(20);\n if (width === 0 || height === 0) return null;\n return { mimeType: 'image/png', width, height };\n}\n\nfunction parseJpeg(buffer: ArrayBuffer): BinaryMetadata | null {\n const bytes = new Uint8Array(buffer);\n let offset = 2;\n\n while (offset + 4 < bytes.byteLength) {\n if (bytes[offset] !== 0xff) return null;\n\n const marker = bytes[offset + 1];\n\n // SOF0 through SOF3 (baseline, progressive, lossless)\n if (marker >= 0xc0 && marker <= 0xc3) {\n if (offset + 9 > bytes.byteLength) return null;\n const view = new DataView(buffer, offset + 5);\n const height = view.getUint16(0);\n const width = view.getUint16(2);\n if (width === 0 || height === 0) return null;\n return { mimeType: 'image/jpeg', width, height };\n }\n\n // Skip non-SOF markers\n if (marker === 0xd8 || marker === 0xd9) {\n offset += 2;\n } else if (marker === 0xff) {\n offset += 1;\n } else {\n const segLen = (bytes[offset + 2] << 8) | bytes[offset + 3];\n offset += 2 + segLen;\n }\n }\n\n return null;\n}\n","import type { FileAttachmentDraft, FileAttachmentWireDraft, WireAttachmentFile } from './draft';\nimport type { AttachmentFileSource } from '../../../dto/Attachment';\nimport { EngineError } from '../../../errors/EngineError';\nimport { EngineErrorCode } from '../../../errors/EngineErrorCode';\nimport {\n resolveBinarySource,\n type WireResource,\n type WireResourceMap,\n} from '../../../resource/BinarySource';\n\n/**\n * Resolve an attachment `file` into its wire halves: metadata into the\n * JSON body, bytes into the resource map. Unlike stamps there is NO\n * format allowlist — attaching arbitrary files is the point — so the\n * declared mime type wins (attachment formats cannot be reliably sniffed;\n * the writer falls back to `application/octet-stream` when absent).\n *\n * Shared by the file-attachment annotation draft (below) and the\n * document-level `attachments.create` mutation — one vocabulary, one\n * normalizer for both homes a file can enter a PDF through.\n */\nexport async function normalizeAttachmentFileSource(\n file: AttachmentFileSource,\n key: string,\n): Promise<{ wireFile: WireAttachmentFile; resource: WireResource }> {\n const resolved = await resolveBinarySource(file.data);\n const name = file.name ?? resolved.name;\n if (!name) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n 'attachment file requires a name — pass { data, name } or a File whose name is set',\n );\n }\n const mimeType = file.mimeType ?? resolved.mimeType;\n return {\n wireFile: {\n resource: key,\n name,\n ...(mimeType !== undefined ? { mimeType } : {}),\n ...(file.description !== undefined ? { description: file.description } : {}),\n },\n resource: { bytes: resolved.bytes, ...(mimeType !== undefined ? { mimeType } : {}), name },\n };\n}\n\nexport async function normalizeFileAttachmentDraft(\n draft: FileAttachmentDraft,\n allocateKey: () => string,\n): Promise<{ wire: FileAttachmentWireDraft; resources: WireResourceMap }> {\n const { file, ...rest } = draft;\n const key = allocateKey();\n const { wireFile, resource } = await normalizeAttachmentFileSource(file, key);\n return { wire: { ...rest, file: wireFile }, resources: { [key]: resource } };\n}\n","import { EngineError } from '../../../errors/EngineError';\nimport { EngineErrorCode } from '../../../errors/EngineErrorCode';\nimport {\n resolveBinarySource,\n type BinarySource,\n type WireResource,\n type WireResourceMap,\n} from '../../../resource/BinarySource';\nimport { sniffBinaryMetadata } from '../../../resource/binaryMetadata';\nimport type { StampDraft, StampWireDraft } from './draft';\nimport type { StampPatch, StampWirePatch } from './patch';\n\n/**\n * Resolve + validate a stamp `source`. Sniffing happens here — before any\n * transport — so callers get a fast `InvalidArg` instead of a worker/HTTP\n * round-trip. The sniffed mime type overwrites whatever was declared.\n */\nasync function resolveStampSource(source: BinarySource): Promise<WireResource> {\n const resolved = await resolveBinarySource(source);\n const meta = sniffBinaryMetadata(resolved.bytes);\n if (!meta) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n 'stamp source must be PNG, JPEG, or single-page PDF bytes (format is detected from the data, not the declared mime type)',\n );\n }\n return { ...resolved, mimeType: meta.mimeType };\n}\n\nexport async function normalizeStampDraft(\n draft: StampDraft,\n allocateKey: () => string,\n): Promise<{ wire: StampWireDraft; resources: WireResourceMap }> {\n const { source, ...rest } = draft;\n const resolved = await resolveStampSource(source);\n const key = allocateKey();\n return { wire: { ...rest, source: { resource: key } }, resources: { [key]: resolved } };\n}\n\nexport async function normalizeStampPatch(\n patch: StampPatch,\n allocateKey: () => string,\n): Promise<{ wire: StampWirePatch; resources: WireResourceMap }> {\n if (patch.source === undefined) {\n const { source: _source, ...rest } = patch;\n return { wire: rest, resources: {} };\n }\n const { source, ...rest } = patch;\n const resolved = await resolveStampSource(source);\n const key = allocateKey();\n return { wire: { ...rest, source: { resource: key } }, resources: { [key]: resolved } };\n}\n","import type {\n AnnotationDraft,\n AnnotationPatch,\n WireAnnotationDraft,\n WireAnnotationPatch,\n} from './kinds';\nimport type { WireResourceMap } from '../resource/BinarySource';\n// Deep imports (not the kind barrels): keeps this module — and the zod-free\n// `shared` entrypoint that re-exports it — free of the kinds' Zod schemas.\nimport { normalizeFileAttachmentDraft } from './kinds/file-attachment/normalize';\nimport { normalizeStampDraft, normalizeStampPatch } from './kinds/stamp/normalize';\n\n/**\n * The one shared splitter between authoring and wire forms — every engine\n * (local, cloud) and no one else runs this; transports never reimplement it.\n *\n * Uniform rule, zero per-kind exceptions: any `BinarySource` field on a\n * draft/patch is replaced by `{ resource: key }` and its bytes move into\n * the returned `WireResourceMap` (worker: transfer list; cloud: multipart\n * `resource:{key}` parts). Kinds without binary fields pass through\n * untouched with an empty map — their wire form IS their authoring form.\n *\n * Zod-free by design: schemas validate the returned wire form; the\n * authoring types are TypeScript-only sugar.\n */\n\nexport interface NormalizedDraft {\n wire: WireAnnotationDraft;\n resources: WireResourceMap;\n}\n\nexport interface NormalizedPatch {\n wire: WireAnnotationPatch;\n resources: WireResourceMap;\n}\n\nfunction createResourceKeyAllocator(): () => string {\n let next = 0;\n return () => `r${next++}`;\n}\n\nexport async function normalizeAnnotationDraft(draft: AnnotationDraft): Promise<NormalizedDraft> {\n switch (draft.subtype) {\n case 'stamp':\n return normalizeStampDraft(draft, createResourceKeyAllocator());\n case 'file-attachment':\n return normalizeFileAttachmentDraft(draft, createResourceKeyAllocator());\n default:\n return { wire: draft, resources: {} };\n }\n}\n\nexport async function normalizeAnnotationPatch(patch: AnnotationPatch): Promise<NormalizedPatch> {\n switch (patch.subtype) {\n case 'stamp':\n return normalizeStampPatch(patch, createResourceKeyAllocator());\n default:\n return { wire: patch, resources: {} };\n }\n}\n","/**\n * Comment-thread composition — the conversation-plane view over the flat\n * annotation list.\n *\n * Where `buildThreads()` (relationships.ts) is the minimal, unopinionated\n * one-level composer, `buildCommentThreads()` is the opinionated one a\n * comments sidebar wants:\n *\n * - the WHOLE `/IRT` subtree of a root is walked (cycle-safe), and its\n * non-state members flatten into one chronological reply list;\n * - ISO 32000 §12.5.6.3 state annotations (review status) are extracted\n * into `review` instead of appearing as replies;\n * - widgets, links, and unsupported blobs (which includes `/Popup`\n * dictionaries) are excluded entirely;\n * - `/RT /Group` subordinates anywhere in the subtree fold into\n * `groupedParts`, never into `replies`.\n *\n * Tolerant-reader rules (foreign files are messy; none of this throws):\n * - empty-string `state` / `stateModel` count as absent — the engine\n * DTO is faithful (`''` = present-but-empty), tolerance lives here;\n * - a state annotation whose target cannot be resolved is DROPPED\n * (status metadata with no anchor has no meaning);\n * - an orphaned non-state reply is PROMOTED to a thread root (matching\n * `buildThreads`), as is the first input-order member of an `/IRT`\n * cycle — the visited set breaks the loop, nothing is lost or hangs;\n * - a `/State` with no `/StateModel` infers its model from the known\n * vocabulary; a custom model with no derivable state is skipped.\n *\n * Ordering: threads appear in the input order of their roots; the\n * composer never sorts by page (display order is a layout concern —\n * callers join `pages.list()`). Replies sort chronologically by\n * `created ?? modified`, entries without a date last, page z-order\n * (`index`) as the final deterministic tiebreak.\n */\n\nimport type { AnnotationDTO } from './kinds';\nimport type { KnownAnnotationState } from './primitives';\nimport { classifyRelation, refKey } from './relationships';\nimport type { AnnotationRef } from '../identity/AnnotationRef';\nimport type { PageObjectNumber } from '../identity/PageObjectNumber';\n\n/** One reviewer's status, derived from an ISO §12.5.6.3 state annotation. */\nexport interface ReviewStatus {\n /** Wire-normalized when known (`'accepted'`, …); verbatim when custom. */\n state: string;\n /** `'review'`, `'marked'`, or a custom model verbatim. */\n stateModel: string;\n /** Reviewer key: `/EMBD_Metadata` userId, else `/T`, else null. */\n by: string | null;\n /** `/M` ?? `/CreationDate` of the state annotation (ISO 8601). */\n at: string | null;\n /** The state annotation itself — for auditing or deletion. */\n ref: AnnotationRef;\n}\n\n/**\n * Review state of one thread. The two ISO state models are independent\n * axes: `byReviewer` / `lastChange` cover the review axis (the standard\n * `Review` model plus custom models), while the personal-checkmark\n * `Marked` axis lives solely in `markedBy`.\n */\nexport interface CommentThreadReview {\n /** Latest review-axis status per reviewer key (unattributed skipped). */\n byReviewer: Record<string, ReviewStatus>;\n /** Latest review-axis change overall — a convenience, NOT a verdict. */\n lastChange: ReviewStatus | null;\n /** Reviewer keys whose latest Marked-model status is `'marked'`. */\n markedBy: string[];\n /**\n * Every state annotation in the thread's subtree (both axes, all\n * reviewers, chronological) — thread MEMBERSHIP, not status history:\n * deleting a whole thread must delete its state annotations too, and\n * the classified summaries above deliberately drop superseded refs.\n */\n statusRefs: AnnotationRef[];\n /** `byReviewer[currentUserId]`; only set when the option was given. */\n mine?: ReviewStatus | null;\n}\n\nexport interface CommentThread<T extends AnnotationDTO = AnnotationDTO> {\n root: T;\n pageObjectNumber: PageObjectNumber;\n /** Whole-subtree replies, flattened chronologically; states excluded. */\n replies: T[];\n /** Every `/RT /Group` subordinate found in the subtree. */\n groupedParts: T[];\n review: CommentThreadReview;\n}\n\nexport interface BuildCommentThreadsOptions {\n /** Compute `review.mine` against this reviewer key. */\n currentUserId?: string;\n}\n\n/** Subtypes that never participate in comment threads. `unsupported`\n * covers `/Popup` dictionaries (raw code 16) and unreadable foreign\n * blobs — neither makes a meaningful comment card. */\nconst EXCLUDED_SUBTYPES: ReadonlySet<string> = new Set(['widget', 'link', 'unsupported']);\n\nconst REVIEW_STATES: ReadonlySet<KnownAnnotationState> = new Set([\n 'accepted',\n 'rejected',\n 'cancelled',\n 'completed',\n 'none',\n]);\nconst MARKED_STATES: ReadonlySet<KnownAnnotationState> = new Set(['marked', 'unmarked']);\n\nconst nonEmpty = (v: string | null | undefined): v is string => typeof v === 'string' && v !== '';\n\n/**\n * An ISO 32000 §12.5.6.3 state annotation: a text annotation carrying a\n * non-empty `/State` or `/StateModel`. Classification never relies on\n * flags — producers disagree on how state annotations are flagged.\n */\nexport function isStateAnnotation(a: AnnotationDTO): boolean {\n return a.subtype === 'text' && (nonEmpty(a.state) || nonEmpty(a.stateModel));\n}\n\nexport function buildCommentThreads(\n annotations: readonly AnnotationDTO[],\n opts: BuildCommentThreadsOptions = {},\n): CommentThread[] {\n const eligible = annotations.filter((a) => !EXCLUDED_SUBTYPES.has(a.subtype));\n\n // Index by ref key, with an /NM alias so a child that addresses its\n // parent by name still resolves when the parent's own ref is\n // objectNumber-form (same dual index as buildThreads). ObjectNumber\n // entries win over nm aliases on duplicate /NM.\n const byKey = new Map<string, AnnotationDTO>();\n for (const a of eligible) {\n const key = refKey(a.ref);\n if (!byKey.has(key)) byKey.set(key, a);\n if (a.nm) {\n const aliasKey = refKey({ kind: 'nm', pageObjectNumber: a.pageObjectNumber, nm: a.nm });\n if (!byKey.has(aliasKey)) byKey.set(aliasKey, a);\n }\n }\n\n // Children adjacency over resolvable /IRT edges.\n const children = new Map<string, AnnotationDTO[]>();\n for (const a of eligible) {\n if (!a.inReplyTo) continue;\n const parent = byKey.get(refKey(a.inReplyTo));\n if (!parent) continue; // orphan — handled in the promotion pass\n const parentKey = refKey(parent.ref);\n const list = children.get(parentKey);\n if (list) list.push(a);\n else children.set(parentKey, [a]);\n }\n\n const visited = new Set<string>();\n const threads: CommentThread[] = [];\n\n const walk = (root: AnnotationDTO): void => {\n const replies: AnnotationDTO[] = [];\n const groupedParts: AnnotationDTO[] = [];\n const states: AnnotationDTO[] = [];\n\n visited.add(refKey(root.ref));\n const stack = [...(children.get(refKey(root.ref)) ?? [])];\n while (stack.length > 0) {\n const a = stack.pop()!;\n const key = refKey(a.ref);\n if (visited.has(key)) continue; // cycle back-edge — skip\n visited.add(key);\n if (isStateAnnotation(a)) states.push(a);\n else if (classifyRelation(a) === 'grouped-subordinate') groupedParts.push(a);\n else replies.push(a);\n stack.push(...(children.get(key) ?? []));\n }\n\n replies.sort(chronological);\n // Chronological order makes latest-wins deterministic for equal or\n // missing dates (the comparator's z-order tiebreak applies).\n states.sort(chronological);\n threads.push({\n root,\n pageObjectNumber: root.pageObjectNumber,\n replies,\n groupedParts,\n review: computeReview(states, opts),\n });\n };\n\n // Pass 1: real roots, in input order.\n for (const a of eligible) {\n if (!a.inReplyTo && !isStateAnnotation(a)) walk(a);\n }\n\n // Pass 2: promotion. Anything not reached from a root — an orphan whose\n // parent is missing, or a member of an /IRT cycle — promotes to its own\n // root in input order. State annotations never promote: a status with no\n // reachable target is dropped.\n for (const a of eligible) {\n if (visited.has(refKey(a.ref))) continue;\n if (isStateAnnotation(a)) continue;\n walk(a);\n }\n\n return threads;\n}\n\n/** `created ?? modified` ascending; undated last; z-order tiebreak. */\nfunction chronological(a: AnnotationDTO, b: AnnotationDTO): number {\n const at = a.created ?? a.modified;\n const bt = b.created ?? b.modified;\n if (at !== null && bt !== null && at !== bt) return at < bt ? -1 : 1;\n if (at !== null && bt === null) return -1;\n if (at === null && bt !== null) return 1;\n return a.index - b.index;\n}\n\nfunction computeReview(\n states: readonly AnnotationDTO[],\n opts: BuildCommentThreadsOptions,\n): CommentThreadReview {\n const byReviewer: Record<string, ReviewStatus> = {};\n const markedLatest: Record<string, ReviewStatus> = {};\n let lastChange: ReviewStatus | null = null;\n\n for (const a of states) {\n const status = toReviewStatus(a);\n if (!status) continue;\n if (status.stateModel === 'marked') {\n if (status.by !== null && isNewer(status, markedLatest[status.by])) {\n markedLatest[status.by] = status;\n }\n continue; // the Marked axis never feeds byReviewer / lastChange\n }\n if (status.by !== null && isNewer(status, byReviewer[status.by])) {\n byReviewer[status.by] = status;\n }\n if (isNewer(status, lastChange)) lastChange = status;\n }\n\n const markedBy = Object.keys(markedLatest)\n .filter((key) => markedLatest[key]!.state === 'marked')\n .sort();\n\n const review: CommentThreadReview = {\n byReviewer,\n lastChange,\n markedBy,\n statusRefs: states.map((a) => a.ref),\n };\n if (opts.currentUserId !== undefined) {\n review.mine = byReviewer[opts.currentUserId] ?? null;\n }\n return review;\n}\n\n/**\n * Derive a `ReviewStatus` from one state annotation, or null when nothing\n * classifiable can be derived. ISO defaulting happens HERE, not in the\n * engine reader: a known model with an absent state means `none` /\n * `unmarked`; an absent model infers from a known state; a custom model\n * with no state has no derivable status.\n */\nfunction toReviewStatus(a: AnnotationDTO): ReviewStatus | null {\n if (a.subtype !== 'text') return null;\n const rawState = nonEmpty(a.state) ? a.state : null;\n const rawModel = nonEmpty(a.stateModel) ? a.stateModel : null;\n\n let stateModel = rawModel;\n if (stateModel === null && rawState !== null) {\n if (REVIEW_STATES.has(rawState as KnownAnnotationState)) stateModel = 'review';\n else if (MARKED_STATES.has(rawState as KnownAnnotationState)) stateModel = 'marked';\n else return null; // custom state without a model: unclassifiable\n }\n let state = rawState;\n if (state === null) {\n if (stateModel === 'review') state = 'none';\n else if (stateModel === 'marked') state = 'unmarked';\n else return null; // custom model without a state: no default exists\n }\n if (stateModel === null) return null; // unreachable, kept for narrowing\n\n return {\n state,\n stateModel,\n by: a.userId ?? (nonEmpty(a.author) ? a.author : null),\n at: a.modified ?? a.created ?? null,\n ref: a.ref,\n };\n}\n\n/** `a` newer than (or supersedes) `b`. `at` decides; dated beats undated.\n * States arrive pre-sorted by `chronological` (date, then z-order), so on\n * equal or missing dates the later entry wins via `>=` / `true`. */\nfunction isNewer(a: ReviewStatus, b: ReviewStatus | null | undefined): boolean {\n if (!b) return true;\n if (a.at !== null && b.at !== null) return a.at >= b.at;\n if (a.at !== null) return true;\n if (b.at !== null) return false;\n return true; // both undated: input order — later entry wins\n}\n","import type { WeakAnnotationState } from '../revision/WeakAnnotationState';\n\nexport type AnnotationMutationKind = 'create' | 'update' | 'delete' | 'move';\n\nexport function changesAnnotationList(_kind: AnnotationMutationKind): boolean {\n return true;\n}\n\nexport function shiftsExistingAnnotationIndices(kind: AnnotationMutationKind): boolean {\n return kind === 'delete' || kind === 'move';\n}\n\nexport function invalidatesWeakIndexRefs(\n kind: AnnotationMutationKind,\n weakStateBefore: WeakAnnotationState,\n): boolean {\n if (!shiftsExistingAnnotationIndices(kind)) {\n return false;\n }\n if (weakStateBefore.kind !== 'known') {\n throw new Error(\n `invalidatesWeakIndexRefs requires a known WeakAnnotationState for ${kind}; got 'unknown'. ` +\n 'Caller must scan the page before computing mutation impact.',\n );\n }\n return weakStateBefore.hasAnyWeakAnnotations;\n}\n","import type { PdfRect } from '../geometry/primitives';\nimport type { AnnotationDTO, WireAnnotationPatch } from './kinds';\n\n/**\n * Appearance-impact classification: the shared, pure decision for whether an\n * update patch requires re-baking the `/AP` normal appearance stream.\n *\n * An `/AP` stream is CONTENT, not cache — a foreign producer's appearance\n * (Acrobat's rich `/AP`, an image-backed stamp) generally cannot be\n * recomputed, so destroying it is only acceptable as the explicit consequence\n * of a semantic edit. Per ISO 32000 §12.5.5 a form XObject's `BBox` is\n * algorithmically fitted into `/Rect`, so a same-size `/Rect` change\n * translates the painted pixels verbatim: preservation on a verified rigid\n * translation is a theorem, not a policy. The engine therefore never trusts a\n * caller's claim of \"this is just a move\" — it checks the geometric fact that\n * licenses preservation.\n *\n * The classifier compares in DTO space on both sides (the patch vocabulary IS\n * the DTO vocabulary, produced by the same readers), so value-diffing drops\n * no-op keys even from clients that send full-object patches. Unknown keys\n * and unknown subtypes classify as `regenerate` — conservative by default.\n */\nexport type AppearanceImpact =\n /** Nothing appearance-affecting changed value — never touch `/AP`. */\n | 'inert'\n /** A verified rigid translation — pixels identical up to translation. */\n | 'translation'\n /** A semantic appearance edit — the owner re-bakes `/AP`. */\n | 'regenerate';\n\n/** What actually happened to `/AP` during an update (the engine's echo). */\nexport type AppearanceAction = 'preserved' | 'regenerated' | 'generation-unavailable';\n\n/**\n * The appearance verdict every `AnnotationUpdateResult` carries. `changed`\n * (not `action`) is the raster-invalidation signal: `true` iff the document's\n * appearance definition changed — a regenerated `/AP`, or appearance-affecting\n * dictionary writes on a subtype the generic generator cannot re-bake.\n */\nexport interface AppearanceOutcome {\n action: AppearanceAction;\n changed: boolean;\n}\n\n/**\n * Coordinate tolerance in PDF user-space points. PDF numbers round-trip\n * through f32 (~7 significant digits) and client-side space conversions, so\n * exact float equality would misclassify no-op writes; 1e-3 pt is far below\n * anything visible while far above accumulated f32 drift at page magnitudes.\n */\nconst EPSILON = 1e-3;\n\n/**\n * Keys that never affect `/AP` on any kind: the discriminator, behavioral\n * flags, reply relationships, grouping, and the conversation-plane\n * entries (`/Subj` subject line, `/State` + `/StateModel` review status —\n * dictionary-only per ISO 32000 §12.5.6.3, never painted).\n */\nconst INERT_KEYS: ReadonlySet<string> = new Set([\n 'subtype',\n 'flags',\n 'inReplyTo',\n 'replyType',\n 'groupId',\n 'subject',\n 'state',\n 'stateModel',\n]);\n\n/**\n * Kinds whose `/AP` paints `/Contents`. Everywhere else `contents` is popup\n * note text — editing a comment must never re-bake (or destroy) the shape's\n * appearance.\n */\nconst CONTENTS_PAINTED: ReadonlySet<string> = new Set(['free-text', 'redact']);\n\n/**\n * The vertex family's `/EMBD_Metadata/Rotation` is an advisory scalar (the\n * vertices are already rotated); it never drives the AP generator, so patches\n * touching it are appearance-inert for these kinds.\n */\nconst ADVISORY_ROTATION: ReadonlySet<string> = new Set(['line', 'polyline', 'polygon', 'ink']);\n\n/**\n * The box kinds carry the `/EMBD_Metadata` transform pair (`rotation` +\n * `unrotatedRect`), tri-state on writes: omitted fields are PRESERVED, `null`\n * (or `0` for rotation) clears. Translation verification therefore compares\n * the after-state — `patch.rotation ?? current.rotation` — not the patch keys.\n */\nconst BOX_TRANSFORM: ReadonlySet<string> = new Set(['square', 'circle', 'free-text', 'stamp']);\n\n/**\n * Per-kind absolute-geometry fields (PDF user space) that a rigid translation\n * shifts together. A kind absent from this table never takes the translation\n * route. `rect` is required in every entry: a translation always moves `/Rect`.\n */\nconst TRANSLATABLE_GEOMETRY: Record<string, readonly string[]> = {\n square: ['rect', 'unrotatedRect'],\n circle: ['rect', 'unrotatedRect'],\n 'free-text': ['rect', 'unrotatedRect', 'calloutLine'],\n line: ['rect', 'linePoints'],\n polygon: ['rect', 'vertices'],\n polyline: ['rect', 'vertices'],\n ink: ['rect', 'inkList'],\n highlight: ['rect', 'quadPoints'],\n underline: ['rect', 'quadPoints'],\n squiggly: ['rect', 'quadPoints'],\n strikeout: ['rect', 'quadPoints'],\n redact: ['rect', 'quadPoints'],\n caret: ['rect'],\n text: ['rect'],\n stamp: ['rect', 'unrotatedRect'],\n 'file-attachment': ['rect'],\n link: ['rect'],\n};\n\nconst numEq = (a: number, b: number): boolean => Math.abs(a - b) <= EPSILON;\n\n/** Degrees normalized to [0,360); absent reads as 0 (no rotation). */\nconst normDeg = (v: unknown): number => {\n const n = typeof v === 'number' ? ((v % 360) + 360) % 360 : 0;\n return n;\n};\n\n/**\n * Semantic equality between a patch value and the current DTO value.\n * Numbers compare within {@link EPSILON}; `null` and `undefined` both mean\n * \"entry absent\" (the tri-state clear of an absent entry is a no-op); arrays\n * and objects compare structurally.\n */\nexport function semanticEqual(a: unknown, b: unknown): boolean {\n if (a == null || b == null) return a == null && b == null;\n if (typeof a === 'number' && typeof b === 'number') return numEq(a, b);\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;\n return a.every((v, i) => semanticEqual(v, b[i]));\n }\n if (typeof a === 'object' && typeof b === 'object') {\n const keys = new Set([...Object.keys(a), ...Object.keys(b as object)]);\n for (const k of keys) {\n if (!semanticEqual((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k])) {\n return false;\n }\n }\n return true;\n }\n return a === b;\n}\n\n/**\n * Is `next` exactly `cur` shifted by `(dx, dy)`? Walks the value structurally:\n * numeric leaves under x-axis keys (`left`/`right`/`x`) must shift by `dx`,\n * y-axis keys (`bottom`/`top`/`y`) by `dy`, and any other numeric leaf must be\n * unchanged. Arrays walk elementwise (same length required).\n */\nfunction shiftedBy(cur: unknown, next: unknown, dx: number, dy: number): boolean {\n if (cur == null || next == null) return cur == null && next == null;\n if (Array.isArray(cur) || Array.isArray(next)) {\n if (!Array.isArray(cur) || !Array.isArray(next) || cur.length !== next.length) return false;\n return cur.every((v, i) => shiftedBy(v, next[i], dx, dy));\n }\n if (typeof cur === 'object' && typeof next === 'object') {\n const keys = new Set([...Object.keys(cur), ...Object.keys(next as object)]);\n for (const k of keys) {\n const c = (cur as Record<string, unknown>)[k];\n const n = (next as Record<string, unknown>)[k];\n if (typeof c === 'number' && typeof n === 'number') {\n const delta =\n k === 'left' || k === 'right' || k === 'x'\n ? dx\n : k === 'bottom' || k === 'top' || k === 'y'\n ? dy\n : 0;\n if (!numEq(c + delta, n)) return false;\n } else if (!shiftedBy(c, n, dx, dy)) {\n return false;\n }\n }\n return true;\n }\n return cur === next;\n}\n\n/**\n * Verify the touched geometry is one rigid translation of the current state.\n * Requires `patch.rect` (a translation always moves `/Rect`) with width and\n * height preserved; every other geometry field present on the annotation must\n * ride along shifted by the same delta — a rect move that leaves `vertices`\n * behind is NOT a translation (the dictionary would desync from the pixels).\n * For box kinds the `/EMBD_Metadata` transform group is checked as an\n * after-state: writes are tri-state (omitted preserves, null/0 clears), so an\n * omitted rotation keeps the current one — but a preserved-yet-unshifted\n * `unrotatedRect` still fails the congruence check via the field loop.\n */\nfunction isRigidTranslation(\n cur: Record<string, unknown>,\n pat: Record<string, unknown>,\n subtype: string,\n geometryKeys: readonly string[],\n): boolean {\n const curRect = cur.rect as PdfRect | undefined;\n const patRect = pat.rect as PdfRect | undefined;\n if (!curRect || !patRect) return false;\n const dx = patRect.left - curRect.left;\n const dy = patRect.bottom - curRect.bottom;\n if (!numEq(patRect.right - patRect.left, curRect.right - curRect.left)) return false;\n if (!numEq(patRect.top - patRect.bottom, curRect.top - curRect.bottom)) return false;\n\n if (BOX_TRANSFORM.has(subtype)) {\n // Tri-state writes: an omitted rotation PRESERVES the current one; `null`\n // clears (≡ 0). Compare the resulting after-state.\n const rotAfter = pat.rotation === undefined ? cur.rotation : pat.rotation;\n if (!numEq(normDeg(cur.rotation), normDeg(rotAfter))) return false;\n }\n\n for (const key of geometryKeys) {\n if (key === 'rect') continue;\n const c = cur[key];\n const p = pat[key];\n if (c == null && p == null) continue; // absent on both — nothing to shift\n if (c == null || p == null) return false; // geometry appearing/vanishing\n if (!shiftedBy(c, p, dx, dy)) return false;\n }\n return true;\n}\n\n/**\n * Classify an update patch against the annotation's current DTO.\n *\n * 1. Value-diff: drop keys whose value semantically equals the current one,\n * plus the always-inert metadata keys (and per-kind inert keys: `contents`\n * where it isn't painted, advisory `rotation` on the vertex family).\n * Nothing left → `'inert'`.\n * 2. If every remaining key is translatable geometry for this kind AND the\n * values are one rigid translation → `'translation'`.\n * 3. Anything else — style, text, unknown keys, unknown kinds → `'regenerate'`.\n */\nexport function appearanceImpactOf(\n current: AnnotationDTO,\n patch: WireAnnotationPatch,\n): AppearanceImpact {\n if (patch.subtype !== current.subtype) return 'regenerate';\n\n const cur = current as unknown as Record<string, unknown>;\n const pat = patch as unknown as Record<string, unknown>;\n const subtype = patch.subtype;\n const caption = pat.caption === undefined ? cur.caption : pat.caption;\n const contentsPainted =\n CONTENTS_PAINTED.has(subtype) ||\n (['line', 'polygon', 'polyline'].includes(subtype) &&\n !!(caption as { enabled?: boolean } | null | undefined)?.enabled);\n\n const touched: string[] = [];\n for (const [key, value] of Object.entries(pat)) {\n if (value === undefined || INERT_KEYS.has(key)) continue;\n if (key === 'contents' && !contentsPainted) continue;\n if (key === 'rotation' && ADVISORY_ROTATION.has(subtype)) continue;\n if (!semanticEqual(value, cur[key])) touched.push(key);\n }\n if (touched.length === 0) return 'inert';\n\n const baseGeometryKeys = TRANSLATABLE_GEOMETRY[subtype];\n // A manual shape caption is page-space geometry and must ride with a rigid\n // move. Automatic centers follow the vertices without an explicit patch.\n const geometryKeys =\n baseGeometryKeys &&\n (subtype === 'polygon' || subtype === 'polyline') &&\n (cur.caption as { center?: unknown } | undefined)?.center\n ? [...baseGeometryKeys, 'caption']\n : baseGeometryKeys;\n if (!geometryKeys) return 'regenerate';\n if (!touched.every((k) => geometryKeys.includes(k))) return 'regenerate';\n return isRigidTranslation(cur, pat, subtype, geometryKeys) ? 'translation' : 'regenerate';\n}\n","import type { PageObjectNumber } from './PageObjectNumber';\n\n/**\n * How callers address a logical form field.\n *\n * - `objectNumber` — the indirect object number of the field dictionary.\n * ISO 32000 guarantees every real AcroForm field dictionary is an\n * indirect object, and the layer runtime never renumbers (frozen base +\n * incremental deltas), so this is the durable identity for the lifetime\n * of a document. Preferred for all engine calls.\n * - `fqn` — the fully qualified field name (\"billing.name\"). The portable,\n * semantic identity used by interchange formats (FDF/XFDF) and analytics;\n * survives document rewrites but is only as unique as the producer made\n * it. The engine resolves it against the reconciled field tree.\n */\nexport type FormFieldRef =\n | { kind: 'objectNumber'; fieldObjectNumber: number }\n | { kind: 'fqn'; name: string };\n\n/**\n * URL-safe encoding of a `FormFieldRef`, used by the cloud HTTP surface as\n * the `:fieldKey` route parameter. Decoded by the server back into a\n * `FormFieldRef` via `decodeFieldRefKey`. Mirrors the annotation plane's\n * `encodeStableIdKey` (`obj:42` / `nm:…`) so the two member-key syntaxes\n * read the same on the wire:\n *\n * `{ kind: 'objectNumber', fieldObjectNumber: 12 }` -> `'obj:12'`\n * `{ kind: 'fqn', name: 'billing.name' }` -> `'fqn:billing.name'`\n *\n * The caller is responsible for `encodeURIComponent`-ing the result before\n * splicing it into a URL path; the `wirePaths.layerFormField*` builders\n * already do that. FQNs are opaque strings and may contain anything; the\n * `fqn:` prefix keeps them unambiguous from numeric ids.\n */\nexport function encodeFieldRefKey(ref: FormFieldRef): string {\n if (ref.kind === 'objectNumber') {\n if (!Number.isInteger(ref.fieldObjectNumber) || ref.fieldObjectNumber <= 0) {\n throw new RangeError(\n `encodeFieldRefKey: fieldObjectNumber must be a positive integer, got ${ref.fieldObjectNumber}`,\n );\n }\n return `obj:${ref.fieldObjectNumber}`;\n }\n return `fqn:${ref.name}`;\n}\n\n/**\n * Inverse of `encodeFieldRefKey`. Returns `null` for malformed input so the\n * server can answer 400 InvalidArg with a useful message instead of\n * throwing. The input is the already-`decodeURIComponent`-ed segment from\n * the route path. Empty FQNs are rejected: `fqn:` with no suffix is not a\n * valid identity.\n */\nexport function decodeFieldRefKey(key: string): FormFieldRef | null {\n if (key.startsWith('obj:')) {\n const rest = key.slice('obj:'.length);\n const n = Number.parseInt(rest, 10);\n if (!Number.isInteger(n) || n <= 0 || String(n) !== rest) return null;\n return { kind: 'objectNumber', fieldObjectNumber: n };\n }\n if (key.startsWith('fqn:')) {\n const name = key.slice('fqn:'.length);\n if (name.length === 0) return null;\n return { kind: 'fqn', name };\n }\n return null;\n}\n\n/** A widget annotation of a field, as the forms subsystem sees it. */\nexport interface FormWidgetRef {\n /**\n * Indirect object number of the widget annotation — the join key to the\n * annotation subsystem's `objectNumber` refs. `0` when the widget is\n * stored as a direct object (spec-violating; cannot be addressed).\n */\n annotObjectNumber: number;\n /**\n * Object number of the page whose /Annots array references the widget.\n * `0` when the widget is not reachable from any page (\"unplaced\").\n */\n pageObjectNumber: PageObjectNumber;\n}\n","import type { PdfValue } from './types';\n\n/**\n * Parse the fork's canonical shallow serialisation:\n * dict <</Key value/Key2 value>> (keys sorted, `#xx`-escaped)\n * array [item item]\n * ref n 0 R\n * stream stream(length,sha256hex)<<dict>>\n * name /Name (with #xx escapes)\n * string (literal with backslash escapes) or <hex>\n * number -12.5 bool true|false null\n */\nexport function parsePdfValue(text: string): PdfValue {\n const parser = new Parser(text);\n const value = parser.value();\n parser.skipSpaces();\n if (!parser.atEnd())\n throw new Error(`trailing input at ${parser.pos}: ${text.slice(parser.pos, parser.pos + 20)}`);\n return value;\n}\n\nclass Parser {\n pos = 0;\n constructor(private readonly text: string) {}\n\n atEnd(): boolean {\n return this.pos >= this.text.length;\n }\n\n skipSpaces(): void {\n while (this.pos < this.text.length && this.text[this.pos] === ' ') this.pos++;\n }\n\n value(): PdfValue {\n this.skipSpaces();\n const t = this.text;\n if (t.startsWith('<<', this.pos)) return this.dict();\n if (t.startsWith('stream(', this.pos)) return this.stream();\n if (t[this.pos] === '[') return this.array();\n if (t[this.pos] === '/') return { t: 'name', v: this.name() };\n if (t[this.pos] === '(') return { t: 'string', v: this.literalString() };\n if (t[this.pos] === '<') return { t: 'string', v: this.hexString() };\n if (t.startsWith('true', this.pos)) {\n this.pos += 4;\n return { t: 'bool', v: true };\n }\n if (t.startsWith('false', this.pos)) {\n this.pos += 5;\n return { t: 'bool', v: false };\n }\n if (t.startsWith('null', this.pos)) {\n this.pos += 4;\n return { t: 'null' };\n }\n const ref = /^(\\d+) 0 R(?![0-9A-Za-z])/.exec(t.slice(this.pos));\n if (ref) {\n this.pos += ref[0].length;\n return { t: 'ref', num: Number(ref[1]) };\n }\n const num = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)/.exec(t.slice(this.pos));\n if (num) {\n this.pos += num[0].length;\n return { t: 'number', v: Number(num[0]) };\n }\n throw new Error(`unexpected input at ${this.pos}: ${t.slice(this.pos, this.pos + 20)}`);\n }\n\n private dict(): PdfValue {\n return { t: 'dict', entries: this.dictEntries() };\n }\n\n private dictEntries(): Record<string, PdfValue> {\n this.expect('<<');\n const entries: Record<string, PdfValue> = {};\n for (;;) {\n this.skipSpaces();\n if (this.text.startsWith('>>', this.pos)) {\n this.pos += 2;\n return entries;\n }\n if (this.text[this.pos] !== '/') throw new Error(`expected a key at ${this.pos}`);\n const key = this.name();\n this.skipSpaces();\n entries[key] = this.value();\n }\n }\n\n private stream(): PdfValue {\n const m = /^stream\\((\\d+),([0-9a-fA-F]*)\\)/.exec(this.text.slice(this.pos));\n if (!m) throw new Error(`malformed stream signature at ${this.pos}`);\n this.pos += m[0].length;\n const dict = this.dictEntries();\n return { t: 'stream', length: Number(m[1]), sha256: m[2].toLowerCase(), dict };\n }\n\n private array(): PdfValue {\n this.expect('[');\n const items: PdfValue[] = [];\n for (;;) {\n this.skipSpaces();\n if (this.text[this.pos] === ']') {\n this.pos++;\n return { t: 'array', items };\n }\n items.push(this.value());\n }\n }\n\n private name(): string {\n this.expect('/');\n let out = '';\n while (this.pos < this.text.length) {\n const ch = this.text[this.pos];\n if (\n ch === ' ' ||\n ch === '/' ||\n ch === '[' ||\n ch === ']' ||\n ch === '<' ||\n ch === '>' ||\n ch === '(' ||\n ch === ')'\n ) {\n break;\n }\n if (ch === '#' && /^[0-9A-Fa-f]{2}/.test(this.text.slice(this.pos + 1, this.pos + 3))) {\n out += String.fromCharCode(parseInt(this.text.slice(this.pos + 1, this.pos + 3), 16));\n this.pos += 3;\n continue;\n }\n out += ch;\n this.pos++;\n }\n return out;\n }\n\n private literalString(): string {\n this.expect('(');\n let depth = 1;\n let out = '';\n while (this.pos < this.text.length) {\n const ch = this.text[this.pos++];\n if (ch === '\\\\') {\n const next = this.text[this.pos++];\n switch (next) {\n case 'n':\n out += '\\n';\n break;\n case 'r':\n out += '\\r';\n break;\n case 't':\n out += '\\t';\n break;\n case 'b':\n out += '\\b';\n break;\n case 'f':\n out += '\\f';\n break;\n case '\\n':\n break;\n case '\\r':\n if (this.text[this.pos] === '\\n') this.pos++;\n break;\n default: {\n const oct = /^[0-7]{1,3}/.exec(this.text.slice(this.pos - 1));\n if (oct) {\n out += String.fromCharCode(parseInt(oct[0], 8));\n this.pos += oct[0].length - 1;\n } else {\n out += next;\n }\n }\n }\n continue;\n }\n if (ch === '(') depth++;\n if (ch === ')') {\n depth--;\n if (depth === 0) return out;\n }\n out += ch;\n }\n throw new Error('unterminated string');\n }\n\n private hexString(): string {\n this.expect('<');\n const end = this.text.indexOf('>', this.pos);\n if (end < 0) throw new Error('unterminated hex string');\n const hex = this.text.slice(this.pos, end).replace(/\\s+/g, '');\n this.pos = end + 1;\n let out = '';\n for (let i = 0; i < hex.length; i += 2) {\n out += String.fromCharCode(parseInt(hex.slice(i, i + 2).padEnd(2, '0'), 16));\n }\n return out;\n }\n\n private expect(token: string): void {\n if (!this.text.startsWith(token, this.pos)) throw new Error(`expected ${token} at ${this.pos}`);\n this.pos += token.length;\n }\n}\n\n/** Structural equality of two parsed values. */\nexport function pdfValueEquals(a: PdfValue | null, b: PdfValue | null): boolean {\n return stableStringify(a) === stableStringify(b);\n}\n\nexport function stableStringify(value: PdfValue | null): string {\n if (value === null) return 'null';\n switch (value.t) {\n case 'dict':\n return `<<${Object.keys(value.entries)\n .sort()\n .map((k) => `/${k} ${stableStringify(value.entries[k])}`)\n .join('')}>>`;\n case 'stream':\n return `stream(${value.length},${value.sha256})${stableStringify({ t: 'dict', entries: value.dict })}`;\n case 'array':\n return `[${value.items.map(stableStringify).join(' ')}]`;\n case 'ref':\n return `${value.num} 0 R`;\n case 'name':\n return `/${encodeName(value.v)}`;\n case 'string':\n return `(${value.v.replace(/[\\\\()]/g, (ch) => `\\\\${ch}`)})`;\n case 'number':\n return String(value.v);\n case 'bool':\n return value.v ? 'true' : 'false';\n case 'null':\n return 'null';\n }\n}\n\nexport function dictEntries(value: PdfValue | null): Record<string, PdfValue> | null {\n if (!value) return null;\n if (value.t === 'dict') return value.entries;\n if (value.t === 'stream') return value.dict;\n return null;\n}\n\n/** Keys whose value differs (added, removed, or changed) between two dictionaries. */\nexport function changedKeys(a: PdfValue | null, b: PdfValue | null): Set<string> {\n const ea = dictEntries(a) ?? {};\n const eb = dictEntries(b) ?? {};\n const out = new Set<string>();\n for (const key of new Set([...Object.keys(ea), ...Object.keys(eb)])) {\n if (!pdfValueEquals(ea[key] ?? null, eb[key] ?? null)) out.add(key);\n }\n return out;\n}\n\nexport function refsOf(value: PdfValue | null | undefined): number[] {\n if (!value) return [];\n if (value.t === 'ref') return [value.num];\n if (value.t === 'array') return value.items.flatMap(refsOf);\n return [];\n}\n\n/** `#xx`-escape a name the way the PDF writer does: delimiters, whitespace, `#`, and non-printables. */\nexport function encodeName(name: string): string {\n let out = '';\n for (const ch of name) {\n const code = ch.charCodeAt(0);\n if (code < 0x21 || code > 0x7e || '#/[]<>(){}%'.includes(ch)) {\n out += `#${code.toString(16).toUpperCase().padStart(2, '0')}`;\n } else {\n out += ch;\n }\n }\n return out;\n}\n","import type { Assessment, ChangeFinding, RevisionAnalysis, StepVerdict } from './types';\n\nconst RANK: Record<StepVerdict, number> = {\n unchanged: 0,\n permitted: 1,\n indeterminate: 2,\n forbidden: 3,\n};\n\n/** The worst of several verdicts (a certification replay's steps). */\nexport function worstVerdict(steps: ReadonlyArray<{ verdict: StepVerdict }>): StepVerdict {\n let worst: StepVerdict = 'unchanged';\n for (const s of steps) if (RANK[s.verdict] > RANK[worst]) worst = s.verdict;\n return worst;\n}\n\n/**\n * One aggregation rule everywhere: a proven violation decides, whatever\n * else could not be established; missing evidence never becomes a pass.\n */\nexport function conclude(\n findings: ReadonlyArray<ChangeFinding>,\n hasEffectiveChanges: boolean,\n): StepVerdict {\n if (findings.some((f) => f.verdict === 'forbidden')) return 'forbidden';\n if (findings.some((f) => f.verdict === 'incomplete')) return 'indeterminate';\n return hasEffectiveChanges ? 'permitted' : 'unchanged';\n}\n\n/** The finding that explains a verdict: the violation, else the gap, else the most notable allowance. */\nexport function primaryFinding(\n findings: ReadonlyArray<ChangeFinding>,\n): ChangeFinding | undefined {\n return (\n findings.find((f) => f.verdict === 'forbidden') ??\n findings.find((f) => f.verdict === 'incomplete') ??\n findings.find((f) => f.verdict === 'permitted')\n );\n}\n\nexport function assessmentOf(step: RevisionAnalysis): Assessment {\n const primary = primaryFinding(step.findings);\n return {\n verdict: step.verdict,\n complete: !step.findings.some((f) => f.verdict === 'incomplete'),\n ...(primary ? { primary } : {}),\n findings: step.findings,\n };\n}\n\n/**\n * A certification window: the net verdict and every replayed step, under\n * the same rule. A step's violation is a violation of the certification\n * even when the final state no longer shows it (corpus v3/83).\n */\nexport function combine(net: RevisionAnalysis, steps: ReadonlyArray<RevisionAnalysis>): Assessment {\n const findings = [...net.findings];\n for (const s of steps) {\n if (s === net) continue;\n for (const f of s.findings) {\n if (f.verdict === 'permitted') continue;\n findings.push({ ...f, detail: `revision ${s.newer}: ${f.detail ?? f.rule}` });\n }\n }\n const verdict = conclude(findings, net.verdict !== 'unchanged' || steps.some((s) => s.verdict !== 'unchanged'));\n const primary = primaryFinding(findings);\n return {\n verdict,\n complete: !findings.some((f) => f.verdict === 'incomplete'),\n ...(primary ? { primary } : {}),\n findings,\n };\n}\n","import type { DocumentFieldLock, ModificationLevel } from '../types';\nimport type { PdfValue } from './types';\nimport { conclude } from './verdict';\nimport { deriveProtection, levelAllows, lockCovers } from '../protection';\nimport { changedKeys, dictEntries, pdfValueEquals, refsOf } from './pdf-value';\nimport type {\n ChangeFinding,\n ObjectChange,\n ObjectReferrer,\n RevisionAnalysis,\n RevisionField,\n RevisionStructure,\n StepInput,\n StepVerdict,\n} from './types';\n\ntype Side = 'old' | 'new';\nconst SIDES: Side[] = ['old', 'new'];\n\nconst TRAILER_KEYS = new Set([\n 'Size',\n 'Prev',\n 'XRefStm',\n 'Info',\n 'ID',\n 'Root',\n 'Type',\n 'W',\n 'Index',\n 'Filter',\n 'DecodeParms',\n 'Length',\n 'Encrypt',\n]);\nconst CATALOG_KEYS = new Set(['Metadata', 'Extensions', 'Version', 'DSS', 'AcroForm', 'Perms']);\nconst ACROFORM_KEYS = new Set(['DR', 'DA', 'Q', 'SigFlags', 'NeedAppearances', 'Fields']);\n/**\n * What a form field may change after a signature, by the level in force.\n * Every key here has a corpus case behind it (`signature-compat`); a key\n * not listed is forbidden until one does.\n *\n * annotate (an approval signature: \"Form Fill-in, Signing and Commenting\n * are allowed\"): everything but the field's identity and its place in\n * the tree. v1/08 /V+/AP, 09 /Ff, 10 /Rect, 11 /F, 18 /TU, 21 /DA; 13 /T\n * forbidden. /AA (v1/12) and /A are accepted by Acrobat and deliberately\n * NOT listed: an action on a signed form is executable content.\n *\n * fill (a P=2 certification): value and appearance. v1/26 /V+/AP, v3/64\n * /Ff (ReadOnly added), 65 /DA, 68 /AP stream; v3/66 /TU, 67 /F, v2/50\n * /Rect forbidden.\n */\nconst FIELD_KEYS_BY_LEVEL: Record<'annotate' | 'fill', ReadonlySet<string>> = {\n annotate: new Set([\n 'V', 'AS', 'AP', 'I', 'DA', 'Ff', 'RV', 'MK', 'Q', 'TU', 'F', 'Rect', 'BS', 'Opt', 'DV', 'MaxLen',\n ]),\n fill: new Set(['V', 'AS', 'AP', 'I', 'RV', 'DA', 'Ff']),\n};\n/** A separate widget dictionary: the presentation subset of the same tables. */\nconst WIDGET_KEYS_BY_LEVEL: Record<'annotate' | 'fill', ReadonlySet<string>> = {\n annotate: new Set(['AS', 'AP', 'DA', 'MK', 'Q', 'TU', 'F', 'Rect', 'BS']),\n fill: new Set(['AS', 'AP', 'DA']),\n};\n/**\n * Signing an EXISTING field: its value, appearance and ReadOnly at any\n * level; after an approval signature also its tooltip and a /Lock installed\n * with the signature (v1/18, 19: both valid; under P=2 the combination is\n * rejected, v3/69, so neither is allowed at `fill`).\n */\nconst SIGNED_FIELD_KEYS_BY_LEVEL: Record<'annotate' | 'fill', ReadonlySet<string>> = {\n annotate: new Set(['V', 'AP', 'AS', 'Ff', 'TU', 'Lock']),\n fill: new Set(['V', 'AP', 'AS', 'Ff']),\n};\nconst SIGNED_WIDGET_KEYS = new Set(['AP', 'AS']);\nconst FF_READ_ONLY = 1;\n\nfunction fieldKeysFor(level: ModificationLevel): ReadonlySet<string> {\n return level === 'annotate' ? FIELD_KEYS_BY_LEVEL.annotate : FIELD_KEYS_BY_LEVEL.fill;\n}\nfunction widgetKeysFor(level: ModificationLevel): ReadonlySet<string> {\n return level === 'annotate' ? WIDGET_KEYS_BY_LEVEL.annotate : WIDGET_KEYS_BY_LEVEL.fill;\n}\nfunction signedFieldKeysFor(level: ModificationLevel): ReadonlySet<string> {\n return level === 'annotate' ? SIGNED_FIELD_KEYS_BY_LEVEL.annotate : SIGNED_FIELD_KEYS_BY_LEVEL.fill;\n}\n\n/**\n * Rules whose permitted findings do not make a revision a CHANGE of the\n * document: an object written again with the sealed value, an object nobody\n * references, a cross-reference container, the trailer's own bookkeeping.\n * A window with nothing else is `unchanged` (Acrobat: \"not modified\").\n */\nconst NON_EFFECTIVE_RULES = new Set(['identical-rewrite', 'orphan', 'xref-container', 'trailer']);\n\n/** The level a step runs at, and the locks it enforces: what the OLDER revision's signatures established. */\nexport function restrictionsOf(before: RevisionStructure): {\n level: ModificationLevel;\n locks: DocumentFieldLock[];\n} {\n const protection = deriveProtection(before.signatures);\n // The JUDGED level: what a validator holds this step to. Nothing signed\n // yet: nothing forbids, the rule set explains what it can.\n return { level: protection.judged ?? 'annotate', locks: protection.fieldLocks };\n}\n\n/**\n * Judge one pairwise step. Every reference to a changed object, in the\n * older AND the newer revision, must be claimed by a rule that inspected\n * that use; an unclaimed reference is `unexplained` and forbidden. A\n * truncated value is `incomplete`, never permitted. Pure: JSON in, JSON\n * out, the same code in the browser worker, on the server and in tests.\n */\nexport function evaluateStep(input: StepInput): RevisionAnalysis {\n const changes = withEvidenceCheck(input.changes);\n const { level, locks } = input.restrictions ?? restrictionsOf(input.before);\n const levelInForce = input.levelOverride ?? level;\n const ctx = new StepContext({ ...input, changes }, levelInForce, locks);\n\n ruleRevisionHealth(ctx);\n ruleXrefContainer(ctx);\n ruleIdenticalRewrite(ctx);\n // Locks first: a frozen object is condemned before any rule could vouch for it.\n ruleFieldLock(ctx);\n ruleTrailer(ctx);\n ruleInfo(ctx);\n ruleMetadata(ctx);\n ruleCatalog(ctx);\n ruleAcroForm(ctx);\n ruleDss(ctx);\n ruleSignatureFieldAdded(ctx);\n ruleSignatureAdded(ctx);\n ruleFormFill(ctx);\n ruleAnnotation(ctx);\n ruleUnexplained(ctx);\n\n const verdict: StepVerdict = conclude(\n ctx.findings,\n ctx.findings.some((f) => f.verdict === 'permitted' && !NON_EFFECTIVE_RULES.has(f.rule)),\n );\n\n return {\n older: input.older,\n newer: input.newer,\n levelInForce,\n locks,\n verdict,\n findings: ctx.findings,\n changes,\n };\n}\n\n/**\n * The evaluator never trusts its transport to be honest about gaps: a side\n * that exists must carry a value, and an object whose value is missing is\n * judged as truncated, whatever the flag says. Cross-reference containers\n * are exempt (their members are judged on their own).\n */\nfunction withEvidenceCheck(changes: ObjectChange[]): ObjectChange[] {\n return changes.map((c) => {\n if (c.value.truncated || c.kind === 'xref' || c.kind === 'objstm') return c;\n const missingOld = c.present.old && (c.value.old === null || c.read?.old === 'failed');\n const missingNew = c.present.new && (c.value.new === null || c.read?.new === 'failed');\n return missingOld || missingNew ? { ...c, value: { ...c.value, truncated: true } } : c;\n });\n}\n\n/**\n * The transport's verdict on each revision as a whole. A sealed revision\n * Acrobat cannot judge later changes to (sparse cross-reference table, a\n * reachable bare-reference object) makes every step over it indeterminate:\n * our verdict would otherwise disagree with the validator recipients use,\n * and for a reason that has nothing to do with the change. An incomplete\n * reachability walk on either side leaves every use unproven.\n */\nfunction ruleRevisionHealth(ctx: StepContext): void {\n const health = ctx.input.health;\n if (!health) return;\n const base = health.old;\n if (base.sparseXref || base.bareReferences > 0) {\n const why = [\n base.sparseXref ? 'its cross-reference table has no entry for some object numbers below /Size' : null,\n base.bareReferences > 0\n ? `${base.bareReferences} reachable indirect object(s) consist of a bare reference`\n : null,\n ]\n .filter((x) => x !== null)\n .join('; ');\n ctx.findings.push({\n rule: 'base-unverifiable',\n verdict: 'incomplete',\n objectNumber: 0,\n detail: `the signed revision cannot be verified against later changes by Acrobat (${why}); no verdict is given rather than one Acrobat would contradict`,\n });\n }\n for (const side of SIDES) {\n if (!health[side].referrersComplete) {\n ctx.findings.push({\n rule: 'unexplained',\n verdict: 'incomplete',\n objectNumber: 0,\n detail: `the ${side === 'old' ? 'older' : 'newer'} revision's reachability walk hit its budget; not every use of a changed object is known`,\n });\n }\n }\n}\n\n/**\n * Same effective value on both sides: same canonical serialisation (keys\n * sorted, whitespace normalised - Acrobat compares dictionaries by value,\n * corpus v3/61-62), same stream data (by bytes, v2/45), and both sides\n * actually read. A failed read serialises as \"null\" and would match another\n * failed read - evidence of nothing.\n */\nexport function sameEffectiveValue(c: ObjectChange): boolean {\n return (\n c.change === 'modified' &&\n !c.value.truncated &&\n c.read?.old !== 'failed' &&\n c.read?.new !== 'failed' &&\n c.raw.old !== null &&\n c.raw.new !== null &&\n c.raw.old === c.raw.new &&\n !c.streamDataChanged\n );\n}\n\n// ---------------------------------------------------------------------------\n\ninterface RoleIndex {\n fieldByObj: Map<number, RevisionField>;\n widgetToField: Map<number, number>;\n pages: Set<number>;\n signedFields: Set<number>;\n sigFields: Set<number>;\n}\n\nfunction indexRoles(s: RevisionStructure): RoleIndex {\n const fieldByObj = new Map<number, RevisionField>();\n const widgetToField = new Map<number, number>();\n const sigFields = new Set<number>();\n for (const f of s.fields) {\n fieldByObj.set(f.objectNumber, f);\n if (f.family === 'signature') sigFields.add(f.objectNumber);\n for (const w of f.widgets) widgetToField.set(w, f.objectNumber);\n }\n const signedFields = new Set<number>();\n for (const sig of s.signatures) {\n if (sig.signed && sig.field.kind === 'objectNumber')\n signedFields.add(sig.field.fieldObjectNumber);\n }\n return { fieldByObj, widgetToField, pages: new Set(s.pages), signedFields, sigFields };\n}\n\nfunction edgeKey(e: ObjectReferrer): string {\n return `${e.parent}:${e.label}`;\n}\n\nclass StepContext {\n readonly findings: ChangeFinding[] = [];\n readonly byNum = new Map<number, ObjectChange>();\n readonly before: RoleIndex;\n readonly after: RoleIndex;\n /**\n * `${objectNumber}:${side}:${edge}` → the rule that inspected the use, and\n * whether it allowed it. A claim explains an edge in the report; only an\n * ALLOWING claim can vouch for a shared object joining a subtree.\n */\n private readonly claims = new Map<string, { rule: string; allow: boolean }>();\n /** Objects a lock forbids touching this step. */\n readonly locked = new Set<number>();\n\n constructor(\n readonly input: StepInput,\n readonly level: ModificationLevel,\n readonly locks: DocumentFieldLock[],\n ) {\n for (const c of input.changes) this.byNum.set(c.objectNumber, c);\n this.before = indexRoles(input.before);\n this.after = indexRoles(input.after);\n }\n\n get changes(): ObjectChange[] {\n return this.input.changes;\n }\n\n allows(needed: ModificationLevel): boolean {\n return levelAllows(this.level, needed);\n }\n\n claimEdge(c: ObjectChange, side: Side, edge: ObjectReferrer, rule: string, allow = true): void {\n if (this.locked.has(c.objectNumber)) return;\n const key = `${c.objectNumber}:${side}:${edgeKey(edge)}`;\n if (!this.claims.has(key)) this.claims.set(key, { rule, allow });\n }\n\n claimAll(c: ObjectChange, rule: string, allow = true): void {\n for (const side of SIDES) for (const e of c.usage[side]) this.claimEdge(c, side, e, rule, allow);\n }\n\n /**\n * Claim the references that are the same in both revisions; a reference\n * gained or lost stays unexplained. `allow: false` explains a condemned\n * object's edges (one cause in the report, not a cascade) without letting\n * anything hang off it.\n */\n claimStable(c: ObjectChange, rule: string, allow = true): void {\n const oldKeys = new Set(c.usage.old.map(edgeKey));\n const newKeys = new Set(c.usage.new.map(edgeKey));\n for (const e of c.usage.old)\n if (newKeys.has(edgeKey(e))) this.claimEdge(c, 'old', e, rule, allow);\n for (const e of c.usage.new)\n if (oldKeys.has(edgeKey(e))) this.claimEdge(c, 'new', e, rule, allow);\n }\n\n isClaimed(c: ObjectChange, side: Side, edge: ObjectReferrer): boolean {\n return this.claims.has(`${c.objectNumber}:${side}:${edgeKey(edge)}`);\n }\n\n /** The use was inspected by a rule that allowed it. */\n isAllowed(c: ObjectChange, side: Side, edge: ObjectReferrer): boolean {\n return this.claims.get(`${c.objectNumber}:${side}:${edgeKey(edge)}`)?.allow === true;\n }\n\n permitted(c: ObjectChange, rule: string, detail?: string): void {\n if (this.locked.has(c.objectNumber)) return;\n this.findings.push({ rule, verdict: 'permitted', objectNumber: c.objectNumber, detail });\n }\n\n /**\n * A violation is only proven on evidence: a rule condemning an object\n * whose value could not be read or inspected is reporting what it could\n * not see, and that is `incomplete`, never `forbidden`.\n */\n forbidden(c: ObjectChange, rule: string, detail: string, edge?: ObjectReferrer): void {\n this.findings.push({\n rule,\n verdict: c.value.truncated ? 'incomplete' : 'forbidden',\n objectNumber: c.objectNumber,\n edge: edge ? edgeKey(edge) : undefined,\n detail: c.value.truncated ? `${detail} (judged on missing evidence: not proven)` : detail,\n });\n }\n\n /**\n * Claim every reference under a set of parents (an appearance subtree,\n * the DSS): objects whose references come from `parents` through labels\n * `accept`, then everything referenced from those objects, and so on.\n * Runs per side, because a replaced appearance stream exists on one\n * side only.\n */\n claimSubtree(\n side: Side,\n roots: Set<number>,\n accept: (label: string) => boolean,\n rule: string,\n ): void {\n // Two sets, never merged: an edge from a ROOT is inside the subtree\n // only through an accepted label, on every pass; an edge from an object\n // that JOINED is inside through any label. Folding the roots into the\n // frontier would let one accepted child (an appearance stream, a DSS\n // update) vouch for every other edge off the same parent.\n const joined = new Set<number>();\n let grew = true;\n while (grew) {\n grew = false;\n for (const c of this.changes) {\n if (roots.has(c.objectNumber) || joined.has(c.objectNumber)) continue;\n if (this.locked.has(c.objectNumber)) continue;\n const edges = c.usage[side];\n if (edges.length === 0) continue;\n const inside = edges.filter(\n (e) => (roots.has(e.parent) && accept(e.label)) || joined.has(e.parent),\n );\n if (inside.length === 0) continue;\n for (const e of inside) this.claimEdge(c, side, e, rule);\n // A changed object joins the subtree - and brings its own children\n // in - only when EVERY use of it is allowed: by this subtree, or by\n // another rule that permitted the owner (a font shared between a\n // filled field's appearance and /AcroForm /DR, corpus v1/16, 21). A\n // use nobody allowed - a signed page's content (v1/30, v2/39, 52),\n // a locked field's appearance (v3/79) - keeps the object, and\n // everything under it, unexplained.\n if (edges.every((e) => inside.includes(e) || this.isAllowed(c, side, e))) {\n joined.add(c.objectNumber);\n grew = true;\n }\n }\n }\n }\n\n isIdentical(c: ObjectChange): boolean {\n return sameEffectiveValue(c);\n }\n\n /** Signatures signed in the newer revision but not the older: this step's signing events. */\n newlySigned(): Array<{\n fieldObjectNumber: number;\n sig: RevisionStructure['signatures'][number];\n }> {\n const out: Array<{ fieldObjectNumber: number; sig: RevisionStructure['signatures'][number] }> =\n [];\n for (const sig of this.input.after.signatures) {\n if (!sig.signed || sig.field.kind !== 'objectNumber') continue;\n if (this.before.signedFields.has(sig.field.fieldObjectNumber)) continue;\n out.push({ fieldObjectNumber: sig.field.fieldObjectNumber, sig });\n }\n return out;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Rules. Each claims the exact references it inspected and records a finding.\n// ---------------------------------------------------------------------------\n\nfunction ruleXrefContainer(ctx: StepContext): void {\n for (const c of ctx.changes) {\n if (c.kind === 'xref' || c.kind === 'objstm') {\n ctx.claimAll(c, 'xref-container');\n ctx.permitted(\n c,\n 'xref-container',\n 'cross-reference container; members are judged on their own',\n );\n }\n }\n}\n\n/**\n * An object written again with the value the sealed revision holds is not\n * a modification: Acrobat compares objects by value and reports such a\n * revision as \"not modified\" for every role tried - document information,\n * a custom catalog entry, a page, the signed signature's own widget, a text\n * field, an annotation, the encryption dictionary, reserialised with keys\n * reordered, under a certification, under a field lock (corpus v1/02-07,\n * 23, v2/47, v3/54-62, 70, 71, 77). Under P=1 nothing is established and\n * the rewrite stays forbidden. Claimed here so the object-kind rules skip\n * it; the verdict treats it as no effective change.\n */\nfunction ruleIdenticalRewrite(ctx: StepContext): void {\n for (const c of ctx.changes) {\n if (!ctx.isIdentical(c)) continue;\n if (ctx.allows('fill')) {\n ctx.claimAll(c, 'identical-rewrite');\n ctx.permitted(c, 'identical-rewrite', 'written again with the sealed value');\n } else {\n ctx.claimAll(c, 'identical-rewrite', false);\n ctx.forbidden(\n c,\n 'identical-rewrite',\n `written again with the sealed value under level '${ctx.level}' (not established for this level)`,\n );\n }\n }\n}\n\nfunction ruleTrailer(ctx: StepContext): void {\n const c = ctx.byNum.get(0);\n if (!c) return;\n const changed = changedKeys(c.value.old, c.value.new);\n const bad = [...changed].filter((k) => !TRAILER_KEYS.has(k));\n const oldRoot = dictEntries(c.value.old)?.Root;\n const newRoot = dictEntries(c.value.new)?.Root;\n if (bad.length > 0) {\n ctx.forbidden(c, 'trailer', `trailer keys changed: ${bad.join(', ')}`);\n return;\n }\n if (changed.has('Root') && !pdfValueEquals(oldRoot ?? null, newRoot ?? null)) {\n ctx.forbidden(c, 'trailer', 'the trailer points at a different catalog');\n return;\n }\n if (\n changed.has('Encrypt') &&\n !pdfValueEquals(\n dictEntries(c.value.old)?.Encrypt ?? null,\n dictEntries(c.value.new)?.Encrypt ?? null,\n )\n ) {\n ctx.forbidden(c, 'trailer', 'the trailer points at a different encryption dictionary');\n return;\n }\n ctx.claimAll(c, 'trailer');\n ctx.permitted(c, 'trailer');\n}\n\nfunction onlyEdges(c: ObjectChange, test: (e: ObjectReferrer) => boolean): boolean {\n const all = [...c.usage.old, ...c.usage.new];\n return all.length > 0 && all.every(test);\n}\n\nfunction ruleInfo(ctx: StepContext): void {\n for (const c of ctx.changes) {\n if (ctx.isIdentical(c)) continue;\n if (c.objectNumber !== 0 && onlyEdges(c, (e) => e.parent === 0 && e.label === 'Info')) {\n ctx.claimAll(c, 'info');\n ctx.permitted(c, 'info', 'document information dictionary');\n }\n }\n}\n\nfunction ruleMetadata(ctx: StepContext): void {\n const roots = new Set([ctx.input.before.root, ctx.input.after.root]);\n for (const c of ctx.changes) {\n if (ctx.isIdentical(c)) continue;\n if (onlyEdges(c, (e) => roots.has(e.parent) && e.label === 'Metadata')) {\n ctx.claimAll(c, 'metadata');\n ctx.permitted(c, 'metadata', 'XMP metadata stream');\n }\n }\n}\n\nfunction ruleCatalog(ctx: StepContext): void {\n const root = ctx.input.after.root;\n const c = ctx.byNum.get(root);\n if (!c || ctx.isIdentical(c)) return;\n const changed = changedKeys(c.value.old, c.value.new);\n const bad = [...changed].filter((k) => !CATALOG_KEYS.has(k));\n if (bad.length > 0) {\n ctx.forbidden(c, 'catalog-housekeeping', `catalog keys changed: ${bad.join(', ')}`);\n return;\n }\n // A DIRECT /AcroForm dictionary changes with the catalog: judge it by the\n // AcroForm rules, and let its default resources ride the catalog's edges.\n if (changed.has('AcroForm') && !ctx.input.after.acroForm && !ctx.input.before.acroForm) {\n const problem = acroFormProblem(\n ctx,\n dictEntries(c.value.old)?.AcroForm ?? null,\n dictEntries(c.value.new)?.AcroForm ?? null,\n );\n if (problem) {\n ctx.forbidden(c, 'acroform-housekeeping', problem);\n return;\n }\n for (const side of SIDES) {\n ctx.claimSubtree(\n side,\n new Set([root]),\n (label) => label.startsWith('AcroForm/DR/'),\n 'acroform-housekeeping',\n );\n }\n }\n if (changed.has('Perms')) {\n const after = deriveProtection(ctx.input.after.signatures);\n const before = deriveProtection(ctx.input.before.signatures);\n if (!after.certification || before.judged !== null) {\n ctx.forbidden(\n c,\n 'catalog-housekeeping',\n '/Perms may only appear with the certification signature, in the first signed revision',\n );\n return;\n }\n }\n ctx.claimAll(c, 'catalog-housekeeping');\n ctx.permitted(c, 'catalog-housekeeping');\n}\n\nfunction ruleAcroForm(ctx: StepContext): void {\n const acro = ctx.input.after.acroForm || ctx.input.before.acroForm;\n if (!acro) return;\n const c = ctx.byNum.get(acro);\n if (!c || ctx.isIdentical(c)) return;\n const problem = acroFormProblem(ctx, c.value.old, c.value.new);\n if (problem) {\n ctx.forbidden(c, 'acroform-housekeeping', problem);\n return;\n }\n ctx.claimAll(c, 'acroform-housekeeping');\n ctx.permitted(c, 'acroform-housekeeping');\n // Default resources (fonts for appearances) live under /DR.\n for (const side of SIDES) {\n ctx.claimSubtree(\n side,\n new Set([acro]),\n (label) => label.startsWith('DR/'),\n 'acroform-housekeeping',\n );\n }\n}\n\n/** What is wrong with an AcroForm dictionary change, or null when it is housekeeping. */\nfunction acroFormProblem(\n ctx: StepContext,\n oldValue: PdfValue | null,\n newValue: PdfValue | null,\n): string | null {\n const changed = changedKeys(oldValue, newValue);\n const bad = [...changed].filter((k) => !ACROFORM_KEYS.has(k));\n if (bad.length > 0) return `AcroForm keys changed: ${bad.join(', ')}`;\n if (changed.has('Fields')) {\n const oldRefs = refsOf(dictEntries(oldValue)?.Fields);\n const newRefs = refsOf(dictEntries(newValue)?.Fields);\n if (oldRefs.length > newRefs.length || oldRefs.some((n, i) => newRefs[i] !== n)) {\n return '/AcroForm /Fields is not append-only';\n }\n const newSigFields = newSignatureFields(ctx);\n const strangers = newRefs.slice(oldRefs.length).filter((n) => !newSigFields.has(n));\n if (strangers.length > 0)\n return `/AcroForm /Fields gained non-signature fields: ${strangers.join(', ')}`;\n }\n return null;\n}\n\n/** The refs appended to an array-valued key when the old array is a prefix of the new one; null otherwise. */\nfunction appendedRefs(c: ObjectChange, key: string): number[] | null {\n const oldItems = dictEntries(c.value.old)?.[key];\n const newItems = dictEntries(c.value.new)?.[key];\n const oldRefs = refsOf(oldItems);\n const newRefs = refsOf(newItems);\n if (oldItems && oldItems.t !== 'array') return null;\n if (!newItems || newItems.t !== 'array') return null;\n if (oldRefs.length > newRefs.length) return null;\n for (let i = 0; i < oldRefs.length; i++) if (oldRefs[i] !== newRefs[i]) return null;\n return newRefs.slice(oldRefs.length);\n}\n\nfunction newSignatureFields(ctx: StepContext): Set<number> {\n const out = new Set<number>();\n for (const n of ctx.after.sigFields) if (!ctx.before.fieldByObj.has(n)) out.add(n);\n return out;\n}\n\nfunction ruleDss(ctx: StepContext): void {\n const roots = new Set([ctx.input.before.root, ctx.input.after.root]);\n for (const side of SIDES) {\n ctx.claimSubtree(side, roots, (label) => label === 'DSS' || label.startsWith('DSS/'), 'dss');\n }\n for (const c of ctx.changes) {\n if (\n c.usage.new.some((e) => roots.has(e.parent) && e.label === 'DSS') &&\n !ctx.findings.some((f) => f.objectNumber === c.objectNumber)\n ) {\n ctx.permitted(c, 'dss', 'document security store');\n }\n }\n}\n\nfunction ruleSignatureFieldAdded(ctx: StepContext): void {\n const added = newSignatureFields(ctx);\n if (added.size === 0) return;\n const rule = 'signature-field-added';\n if (!ctx.allows('fill')) {\n for (const n of added) {\n const c = ctx.byNum.get(n);\n if (c) ctx.forbidden(c, rule, `a signature field was added under level '${ctx.level}'`);\n }\n return;\n }\n const newWidgets = new Set<number>();\n for (const n of added) {\n const field = ctx.after.fieldByObj.get(n)!;\n const c = ctx.byNum.get(n);\n if (c) {\n ctx.claimAll(c, rule);\n ctx.permitted(c, rule, `new signature field \"${field.name}\"`);\n }\n for (const w of field.widgets) {\n newWidgets.add(w);\n if (w === n) continue;\n const wc = ctx.byNum.get(w);\n if (wc) {\n ctx.claimAll(wc, rule);\n ctx.permitted(wc, rule, `widget of new signature field \"${field.name}\"`);\n }\n }\n }\n // The page that lists the new widget: /Annots append-only.\n for (const p of ctx.after.pages) {\n const c = ctx.byNum.get(p);\n if (!c || ctx.isIdentical(c)) continue;\n const changed = changedKeys(c.value.old, c.value.new);\n if (changed.size !== 1 || !changed.has('Annots')) continue;\n const appended = appendedRefs(c, 'Annots');\n if (appended && appended.every((n) => newWidgets.has(n))) {\n ctx.claimAll(c, rule);\n ctx.permitted(c, rule, 'page /Annots gained the new signature widget');\n }\n }\n // A parent field whose /Kids gained the new field.\n for (const c of ctx.changes) {\n if (c.kind !== 'dictionary' || ctx.isIdentical(c)) continue;\n const changed = changedKeys(c.value.old, c.value.new);\n if (changed.size !== 1 || !changed.has('Kids')) continue;\n const appended = appendedRefs(c, 'Kids');\n if (\n appended &&\n appended.length > 0 &&\n appended.every((n) => added.has(n) || newWidgets.has(n))\n ) {\n ctx.claimAll(c, rule);\n ctx.permitted(c, rule, 'field /Kids gained the new signature field');\n }\n }\n}\n\nfunction ruleSignatureAdded(ctx: StepContext): void {\n const rule = 'signature-added';\n const events = ctx.newlySigned();\n if (events.length === 0) return;\n const addedThisStep = newSignatureFields(ctx);\n const beforeProtection = deriveProtection(ctx.input.before.signatures);\n const afterProtection = deriveProtection(ctx.input.after.signatures);\n const parents = new Set<number>();\n const values = new Set<number>();\n for (const { fieldObjectNumber, sig } of events) {\n const needed: ModificationLevel = sig.kind === 'timestamp' ? 'lta' : 'fill';\n if (!ctx.allows(needed)) {\n const c = ctx.byNum.get(fieldObjectNumber);\n if (c) ctx.forbidden(c, rule, `a ${sig.kind} was added under level '${ctx.level}'`);\n continue;\n }\n if (sig.catalogCertification && beforeProtection.judged !== null) {\n const c = ctx.byNum.get(fieldObjectNumber);\n if (c) ctx.forbidden(c, rule, 'a certification signature after another signature');\n continue;\n }\n const field = ctx.after.fieldByObj.get(fieldObjectNumber);\n parents.add(fieldObjectNumber);\n for (const w of field?.widgets ?? []) parents.add(w);\n\n // A field added in this very step was judged, and its edges claimed, by\n // signature-field-added; the table below is for signing an EXISTING\n // field. Before the first signature nothing governs the document, and\n // the /Lock mirror written at authoring time is legitimate whatever the\n // level.\n const fieldIsNew = addedThisStep.has(fieldObjectNumber);\n const allowedFieldKeys =\n beforeProtection.judged === null\n ? new Set([...signedFieldKeysFor(ctx.level), 'Lock'])\n : signedFieldKeysFor(ctx.level);\n const fc = ctx.byNum.get(fieldObjectNumber);\n if (fc && fieldIsNew) {\n ctx.permitted(fc, rule, `new field \"${sig.fieldName}\" signed`);\n } else if (fc && !ctx.isIdentical(fc)) {\n const changed = changedKeys(fc.value.old, fc.value.new);\n const bad = [...changed].filter((k) => !allowedFieldKeys.has(k));\n // A condemned field still claims its stable edges: the report names\n // the cause once, not once per reference to the field.\n if (bad.length > 0) {\n ctx.forbidden(fc, rule, `signature field keys changed: ${bad.join(', ')}`);\n ctx.claimStable(fc, rule, false);\n } else if (\n changed.has('Ff') &&\n !readOnlyOnlyChange(fc, ctx.before.fieldByObj.get(fieldObjectNumber)?.flags)\n ) {\n ctx.forbidden(fc, rule, 'signature field flags changed beyond ReadOnly');\n ctx.claimStable(fc, rule, false);\n } else {\n ctx.claimStable(fc, rule);\n ctx.permitted(fc, rule, `field \"${sig.fieldName}\" signed`);\n }\n }\n for (const w of field?.widgets ?? []) {\n if (w === fieldObjectNumber || fieldIsNew) continue;\n const wc = ctx.byNum.get(w);\n if (!wc || ctx.isIdentical(wc)) continue;\n const bad = [...changedKeys(wc.value.old, wc.value.new)].filter(\n (k) => !SIGNED_WIDGET_KEYS.has(k),\n );\n if (bad.length > 0) {\n ctx.forbidden(wc, rule, `signature widget keys changed: ${bad.join(', ')}`);\n ctx.claimStable(wc, rule, false);\n continue;\n }\n ctx.claimStable(wc, rule);\n ctx.permitted(wc, rule, 'signature widget appearance');\n }\n // The /V value (referenced from the field, and from /Perms for a\n // certification) and the /Lock dictionary installed with the signature.\n // Claimed even when the field itself was condemned above: the report\n // then names one cause, not a cascade of unexplained edges.\n for (const c of ctx.changes) {\n if (c.change !== 'added') continue;\n const asValue = c.usage.new.filter((e) => e.parent === fieldObjectNumber && e.label === 'V');\n const asLock = c.usage.new.filter(\n (e) => e.parent === fieldObjectNumber && e.label === 'Lock',\n );\n const type = dictEntries(c.value.new)?.Type;\n if (asValue.length > 0) {\n const isSig = type?.t === 'name' && (type.v === 'Sig' || type.v === 'DocTimeStamp');\n if (!isSig && type !== undefined) continue;\n for (const e of c.usage.new) {\n if ((e.parent === fieldObjectNumber && e.label === 'V') || e.label === 'DocMDP')\n ctx.claimEdge(c, 'new', e, rule);\n }\n ctx.permitted(c, rule, 'signature value');\n values.add(c.objectNumber);\n } else if (asLock.length > 0) {\n const isLock = type === undefined || (type.t === 'name' && type.v === 'SigFieldLock');\n if (!isLock) continue;\n for (const e of asLock) ctx.claimEdge(c, 'new', e, rule);\n ctx.permitted(c, rule, 'field lock installed with the signature');\n }\n }\n }\n // /Perms: only with the certification, only in the first signed revision.\n if (afterProtection.certification && beforeProtection.judged === null) {\n const root = ctx.input.after.root;\n for (const c of ctx.changes) {\n if (c.change === 'added' && onlyEdges(c, (e) => e.parent === root && e.label === 'Perms')) {\n ctx.claimAll(c, rule);\n ctx.permitted(c, rule, 'certification permissions');\n }\n }\n }\n // Appearance streams and their resources, through the signed field or its\n // widget; and the signature value's own indirect children (/Prop_Build and\n // the like, v1/20), which the value dictionary brings with it.\n for (const side of SIDES)\n ctx.claimSubtree(side, parents, (label) => label === 'AP' || label.startsWith('AP/'), rule);\n if (values.size > 0) ctx.claimSubtree('new', values, () => true, rule);\n}\n\n/**\n * Did `/Ff` change by gaining ReadOnly and nothing else? `/Ff` is\n * inheritable, and a lock writes `effective | ReadOnly` into the terminal\n * dictionary, so a terminal that carried no `/Ff` of its own is judged\n * against the effective flags the older revision's form model reported.\n */\nfunction readOnlyOnlyChange(c: ObjectChange, effectiveBefore?: number): boolean {\n const oldFf = dictEntries(c.value.old)?.Ff;\n const newFf = dictEntries(c.value.new)?.Ff;\n const before = oldFf?.t === 'number' ? oldFf.v : (effectiveBefore ?? 0);\n const after = newFf?.t === 'number' ? newFf.v : 0;\n return (before | FF_READ_ONLY) === after;\n}\n\nfunction ruleFormFill(ctx: StepContext): void {\n const rule = 'form-fill';\n const fieldKeys = fieldKeysFor(ctx.level);\n const widgetKeys = widgetKeysFor(ctx.level);\n const parents = new Set<number>();\n const fields = new Map<number, RevisionField>([\n ...ctx.before.fieldByObj,\n ...ctx.after.fieldByObj,\n ]);\n for (const [num, field] of fields) {\n if (field.family === 'signature') continue;\n const fc = ctx.byNum.get(num);\n const widgetChanges = field.widgets\n .filter((w) => w !== num)\n .map((w) => ctx.byNum.get(w))\n .filter(Boolean) as ObjectChange[];\n // An appearance regenerated under an untouched field and widget (viewers\n // do this for NeedAppearances): the objects hanging off the field's or a\n // widget's /AP. Form filling at P=2 covers it (pyHanko agrees); what the\n // subtree may contain is still judged by the claim below.\n const owners = new Set([num, ...field.widgets]);\n const isAp = (label: string) => label === 'AP' || label.startsWith('AP/');\n // An appearance object shared with another field's /AP is nobody's\n // regeneration (pyHanko: \"used in multiple contexts\"); its foreign edge\n // stays unexplained unless that field is filled in the same step.\n const appearanceOnly =\n !fc && widgetChanges.length === 0\n ? ctx.changes.filter(\n (c) =>\n SIDES.some((side) =>\n c.usage[side].some((e) => owners.has(e.parent) && isAp(e.label)),\n ) &&\n SIDES.every((side) =>\n c.usage[side].every((e) => !isAp(e.label) || owners.has(e.parent)),\n ),\n )\n : [];\n if (!fc && widgetChanges.length === 0 && appearanceOnly.length === 0) continue;\n if (!ctx.allows('fill')) {\n for (const c of [fc, ...widgetChanges, ...appearanceOnly])\n if (c && !ctx.isIdentical(c))\n ctx.forbidden(c, rule, `form fill under level '${ctx.level}'`);\n continue;\n }\n if (appearanceOnly.length > 0) {\n for (const c of appearanceOnly)\n ctx.permitted(c, rule, `appearance of field \"${field.name}\" regenerated`);\n parents.add(num);\n for (const w of field.widgets) parents.add(w);\n continue;\n }\n let ok = true;\n if (fc && !ctx.isIdentical(fc)) {\n const changed = changedKeys(fc.value.old, fc.value.new);\n const bad = [...changed].filter((k) => !fieldKeys.has(k));\n if (bad.length > 0) {\n ctx.forbidden(fc, rule, `field \"${field.name}\" keys changed: ${bad.join(', ')}`);\n ctx.claimStable(fc, rule, false);\n ok = false;\n } else if (\n changed.has('Ff') &&\n !readOnlyOnlyChange(fc, ctx.before.fieldByObj.get(num)?.flags)\n ) {\n // ReadOnly may be ADDED, on its own (v1/09, v3/64, 76); no other bit\n // has a case behind it.\n ctx.forbidden(fc, rule, `field \"${field.name}\" flags changed beyond adding ReadOnly`);\n ctx.claimStable(fc, rule, false);\n ok = false;\n } else {\n ctx.claimStable(fc, rule);\n const properties = [...changed].filter((k) => k !== 'V' && k !== 'AP' && k !== 'AS' && k !== 'I' && k !== 'RV');\n ctx.permitted(\n fc,\n rule,\n properties.length > 0\n ? `field \"${field.name}\" ${changed.has('V') || changed.has('AS') ? 'filled, ' : ''}properties changed: ${properties.join(', ')}`\n : `field \"${field.name}\" filled`,\n );\n }\n }\n for (const wc of widgetChanges) {\n if (ctx.isIdentical(wc)) continue;\n const bad = [...changedKeys(wc.value.old, wc.value.new)].filter((k) => !widgetKeys.has(k));\n if (bad.length > 0) {\n ctx.forbidden(wc, rule, `widget of \"${field.name}\" keys changed: ${bad.join(', ')}`);\n ctx.claimStable(wc, rule, false);\n ok = false;\n continue;\n }\n ctx.claimStable(wc, rule);\n ctx.permitted(wc, rule, `widget of \"${field.name}\" appearance`);\n }\n if (ok) {\n parents.add(num);\n for (const w of field.widgets) parents.add(w);\n }\n }\n for (const side of SIDES)\n ctx.claimSubtree(side, parents, (label) => label === 'AP' || label.startsWith('AP/'), rule);\n}\n\nfunction ruleAnnotation(ctx: StepContext): void {\n const rule = 'annotation';\n const pages = new Set([...ctx.before.pages, ...ctx.after.pages]);\n const widgets = new Set([...ctx.before.widgetToField.keys(), ...ctx.after.widgetToField.keys()]);\n const isWidget = (c: ObjectChange): boolean => {\n if (widgets.has(c.objectNumber)) return true;\n const sub = dictEntries(c.value.new ?? c.value.old)?.Subtype;\n return sub?.t === 'name' && sub.v === 'Widget';\n };\n const annots: ObjectChange[] = [];\n for (const c of ctx.changes) {\n if (c.kind !== 'dictionary' || ctx.isIdentical(c)) continue;\n const onPage = [...c.usage.old, ...c.usage.new].some(\n (e) => pages.has(e.parent) && e.label.startsWith('Annots/'),\n );\n if (onPage && !isWidget(c)) annots.push(c);\n }\n if (annots.length === 0) {\n // Pages whose /Annots changed without a known annotation are judged below.\n }\n if (!ctx.allows('annotate')) {\n for (const c of annots) ctx.forbidden(c, rule, `annotation change under level '${ctx.level}'`);\n return;\n }\n const parents = new Set<number>();\n for (const c of annots) {\n ctx.claimAll(c, rule);\n ctx.permitted(c, rule, `${c.change} annotation`);\n parents.add(c.objectNumber);\n }\n for (const p of pages) {\n const c = ctx.byNum.get(p);\n if (!c || ctx.isIdentical(c)) continue;\n const changed = changedKeys(c.value.old, c.value.new);\n if (changed.size === 1 && changed.has('Annots')) {\n const removed = refsOf(dictEntries(c.value.old)?.Annots).filter(\n (n) => !refsOf(dictEntries(c.value.new)?.Annots).includes(n),\n );\n const added = refsOf(dictEntries(c.value.new)?.Annots).filter(\n (n) => !refsOf(dictEntries(c.value.old)?.Annots).includes(n),\n );\n const touchesWidget = [...removed, ...added].some(\n (n) =>\n widgets.has(n) &&\n !ctx.findings.some((f) => f.objectNumber === n && f.verdict === 'permitted'),\n );\n if (touchesWidget) {\n ctx.forbidden(c, rule, 'page /Annots added or removed a form widget');\n continue;\n }\n ctx.claimAll(c, rule);\n ctx.permitted(c, rule, 'page /Annots changed');\n }\n }\n for (const side of SIDES) {\n ctx.claimSubtree(\n side,\n parents,\n (label) => label === 'AP' || label.startsWith('AP/') || label === 'Popup' || label === 'IRT',\n rule,\n );\n }\n}\n\nfunction ruleFieldLock(ctx: StepContext): void {\n if (ctx.locks.length === 0) return;\n const lockedFields = ctx.input.before.fields.filter((f) =>\n ctx.locks.some((l) => lockCovers(l.spec, f.name)),\n );\n const lockedObjects = new Set<number>();\n for (const f of lockedFields) {\n lockedObjects.add(f.objectNumber);\n for (const w of f.widgets) lockedObjects.add(w);\n }\n // Their appearance subtrees (old side: what the lock froze).\n const frontier = new Set(lockedObjects);\n let grew = true;\n while (grew) {\n grew = false;\n for (const c of ctx.changes) {\n if (frontier.has(c.objectNumber)) continue;\n if (c.usage.old.length > 0 && c.usage.old.every((e) => frontier.has(e.parent))) {\n frontier.add(c.objectNumber);\n grew = true;\n }\n }\n }\n for (const c of ctx.changes) {\n if (!frontier.has(c.objectNumber) || ctx.isIdentical(c)) continue;\n const field = lockedFields.find(\n (f) => f.objectNumber === c.objectNumber || f.widgets.includes(c.objectNumber),\n );\n // A locked field may still gain ReadOnly and nothing else (v3/76: \"not\n // modified\"). Its value, appearance, tooltip, visibility and placement\n // are frozen (v1/28, v2/51, v3/73, 74, 80; 49 and 75 are accepted by\n // Acrobat and kept frozen on purpose: a lock that lets the field move\n // or redraw is not the guarantee it promises).\n if (field && field.objectNumber === c.objectNumber) {\n const changed = changedKeys(c.value.old, c.value.new);\n if (\n changed.size === 1 &&\n changed.has('Ff') &&\n readOnlyOnlyChange(c, ctx.before.fieldByObj.get(c.objectNumber)?.flags)\n ) {\n ctx.claimStable(c, 'field-lock');\n ctx.permitted(c, 'field-lock', `ReadOnly set on locked field \"${field.name}\"`);\n continue;\n }\n }\n ctx.locked.add(c.objectNumber);\n ctx.forbidden(\n c,\n 'field-lock',\n field\n ? `field \"${field.name}\" is locked by the signature`\n : 'part of a locked field changed',\n );\n }\n}\n\nfunction ruleUnexplained(ctx: StepContext): void {\n for (const c of ctx.changes) {\n if (c.value.truncated) {\n ctx.findings.push({\n rule: 'unexplained',\n verdict: 'incomplete',\n objectNumber: c.objectNumber,\n detail: 'value too large to inspect',\n });\n continue;\n }\n if (c.usageIncomplete) {\n ctx.findings.push({\n rule: 'unexplained',\n verdict: 'incomplete',\n objectNumber: c.objectNumber,\n detail: 'references could not be resolved within budget (depth, fan-out or total reads)',\n });\n continue;\n }\n if (ctx.locked.has(c.objectNumber)) continue;\n for (const side of SIDES) {\n for (const e of c.usage[side]) {\n if (!ctx.isClaimed(c, side, e)) {\n ctx.forbidden(\n c,\n 'unexplained',\n `${side === 'old' ? 'was' : 'is'} referenced from object ${e.parent} at ${e.label} and no rule explains it`,\n e,\n );\n }\n }\n }\n if (\n c.usage.old.length === 0 &&\n c.usage.new.length === 0 &&\n !ctx.findings.some((f) => f.objectNumber === c.objectNumber)\n ) {\n ctx.permitted(c, 'orphan', 'referenced from nowhere reachable');\n }\n }\n}\n","import type { DocumentFieldLock, ModificationLevel, SignatureDTO } from '../types';\nimport { APPROVAL_BASELINE, levelFromPermission, minLevel } from '../protection';\nimport type { RestrictionAnchor, RevisionStructure } from './types';\n\n/**\n * The restrictions a window is judged under, read from the SEALED\n * revision's structure (what that revision declared, not what the final\n * file says).\n *\n * - `judged` given (a signature-anchored analysis): its own FieldMDP and\n * /Lock bind the window; other signatures' locks do not (corpus v3/85:\n * a second signature is valid with a fill of a field the first locked).\n * Every certification's level, own or earlier, applies (inherited:\n * conservative until observed otherwise), as does a /Lock's /P.\n * - no `judged` (a revision-anchored analysis): every signed signature's\n * locks and levels, as before.\n */\nexport function restrictionsFor(\n before: RevisionStructure,\n judged: SignatureDTO | null,\n): { anchors: RestrictionAnchor[]; level: ModificationLevel; locks: DocumentFieldLock[] } {\n const anchors: RestrictionAnchor[] = [];\n const locks: DocumentFieldLock[] = [];\n let enforced: ModificationLevel | null = null;\n let signed = false;\n for (const sig of before.signatures) {\n if (!sig.signed || sig.revisionIndex === null) continue;\n signed = true;\n const own = judged !== null && sig.index === judged.index;\n if (sig.catalogCertification && sig.docMdp !== null) {\n anchors.push({\n signatureIndex: sig.index,\n revisionIndex: sig.revisionIndex,\n source: 'docmdp',\n own,\n permission: sig.docMdp,\n });\n enforced = minLevel(enforced ?? 'annotate', levelFromPermission(sig.docMdp));\n }\n if (sig.lock?.permission !== undefined) {\n enforced = minLevel(enforced ?? 'annotate', levelFromPermission(sig.lock.permission));\n }\n if (judged !== null && !own) continue;\n if (sig.fieldMdp) {\n anchors.push({\n signatureIndex: sig.index,\n revisionIndex: sig.revisionIndex,\n source: 'fieldmdp',\n own,\n fields: sig.fieldMdp,\n });\n locks.push({ signatureIndex: sig.index, source: 'fieldmdp', spec: sig.fieldMdp });\n }\n if (sig.lock) {\n anchors.push({\n signatureIndex: sig.index,\n revisionIndex: sig.revisionIndex,\n source: 'lock',\n own,\n fields: sig.lock,\n });\n locks.push({ signatureIndex: sig.index, source: 'lock', spec: sig.lock });\n }\n }\n const level = signed ? (enforced ?? APPROVAL_BASELINE) : 'annotate';\n return { anchors, level, locks };\n}\n","import type { ObjectReferrer } from './types';\n\n/**\n * Limits on edge resolution. Exceeding any of them makes the object's usage\n * `incomplete`, which the evaluator turns into an indeterminate step: an\n * adversary can make evidence expensive, never make it disappear.\n */\nexport interface EdgeResolverBudget {\n /** Longest chain of unchanged objects an edge may be resolved through. */\n maxDepth: number;\n /** Most anchored edges one object may end up with. */\n maxEdgesPerObject: number;\n /** Most referrer reads per resolver (one per side per step). */\n maxReads: number;\n}\n\nexport const DEFAULT_EDGE_RESOLVER_BUDGET: EdgeResolverBudget = {\n maxDepth: 16,\n maxEdgesPerObject: 256,\n maxReads: 20_000,\n};\n\nexport const USAGE_INCOMPLETE = 'incomplete';\nexport type ResolvedUsage = ObjectReferrer[] | typeof USAGE_INCOMPLETE;\n\ninterface Resolution {\n edges: ObjectReferrer[];\n /** A cycle was skipped while computing this: do not memoise. */\n cyclic: boolean;\n}\n\n/**\n * Resolves the raw inbound edges of an object (from the fork's referrer\n * index, which covers every reachable object of a revision) into edges\n * from *anchors*: the changed objects and the structural objects of the\n * revision (trailer, catalog, AcroForm, page tree root, pages, fields,\n * widgets). An edge from an unchanged, non-structural parent is replaced by\n * that parent's own anchored edges with the labels joined, so an\n * appearance stream under an unchanged indirect `/AP` dictionary reads\n * `widget:AP/N` rather than `apDict:N`.\n *\n * A graph traversal, not a path enumeration: results are memoised per\n * object, so a lattice of shared unchanged objects costs its size, not the\n * number of paths through it. Cycle edges contribute no anchors and are\n * skipped; a result computed while skipping one is not memoised.\n */\nexport class EdgeResolver {\n private readonly memo = new Map<number, Resolution>();\n private reads = 0;\n private exhausted = false;\n\n constructor(\n private readonly read: (objectNumber: number) => ObjectReferrer[],\n private readonly anchors: ReadonlySet<number>,\n private readonly budget: EdgeResolverBudget = DEFAULT_EDGE_RESOLVER_BUDGET,\n ) {}\n\n /** Anchored edges of `objectNumber`, or `incomplete` when a budget was exceeded. */\n resolve(objectNumber: number): ResolvedUsage {\n if (this.exhausted) return USAGE_INCOMPLETE;\n const result = this.resolveInner(objectNumber, new Set());\n return result === null ? USAGE_INCOMPLETE : result.edges;\n }\n\n private resolveInner(n: number, active: Set<number>): Resolution | null {\n const hit = this.memo.get(n);\n if (hit) return hit;\n if (active.size >= this.budget.maxDepth) return null;\n if (this.reads >= this.budget.maxReads) {\n this.exhausted = true;\n return null;\n }\n this.reads += 1;\n const raw = this.read(n);\n\n active.add(n);\n const edges: ObjectReferrer[] = [];\n let cyclic = false;\n try {\n for (const e of raw) {\n if (this.anchors.has(e.parent)) {\n edges.push(e);\n } else if (active.has(e.parent)) {\n cyclic = true; // a loop back into the chain: no new anchor lies that way\n continue;\n } else {\n const up = this.resolveInner(e.parent, active);\n if (up === null) return null;\n cyclic ||= up.cyclic;\n for (const u of up.edges) {\n edges.push({\n parent: u.parent,\n label: `${u.label}/${e.label}`,\n via: [...(u.via ?? []), e.parent],\n });\n }\n }\n if (edges.length > this.budget.maxEdgesPerObject) return null;\n }\n } finally {\n active.delete(n);\n }\n const resolution = { edges, cyclic };\n if (!cyclic) this.memo.set(n, resolution);\n return resolution;\n }\n}\n","import { foldText, toOriginalRange } from './fold';\nimport type { FoldedText, FoldOptions, SearchMatchRange } from './fold';\nimport type { SearchQuery } from './types';\n\n/**\n * The fold flavor a literal query needs. Haystack and needle MUST be\n * folded with the same options; corpus caches key their pre-folded text\n * on this (the default `{}` fold is the persistable one — non-default\n * queries fold the original page text at query time).\n */\nexport function foldOptionsFor(query: SearchQuery): FoldOptions {\n return {\n keepCase: !!query.matchCase,\n keepMarks: !!query.matchDiacritics,\n dropWhitespace: !!query.ignoreWhitespace,\n };\n}\n\n// ONE definition of \"word character\" for the whole search subsystem —\n// Unicode letters/digits, not JS \\b's ASCII set — shared by the literal\n// boundary check and the regex wholeWord post-filter, so the wholeWord\n// toggle means the same thing in both modes (\"caf\" never whole-word\n// matches inside \"café\", regex or not).\nconst WORD_UNIT = /[\\p{L}\\p{N}_]/u;\nconst MARK = /\\p{M}/u;\n\n/** Whether the code point ENDING at `index` (exclusive) is a word char. */\nexport function wordBefore(text: string, index: number): boolean {\n if (index <= 0) return false;\n // Step back over a low surrogate to test the full code point.\n const unit = text.charCodeAt(index - 1);\n const start = unit >= 0xdc00 && unit <= 0xdfff && index >= 2 ? index - 2 : index - 1;\n return WORD_UNIT.test(String.fromCodePoint(text.codePointAt(start)!));\n}\n\n/** Whether the code point starting at `index` is a word char. */\nexport function wordAt(text: string, index: number): boolean {\n if (index >= text.length) return false;\n return WORD_UNIT.test(String.fromCodePoint(text.codePointAt(index)!));\n}\n\n/**\n * Whether the folded hit at `at` sits on word boundaries. Checked on the\n * folded plane, except under `ignoreWhitespace`: dropping whitespace glues\n * neighbouring words together (\"i n v o i c e 42\" folds to \"invoice42\"), so there the\n * boundaries are read off the ORIGINAL text around the mapped range.\n */\nfunction isWholeWordHit(\n haystack: FoldedText,\n at: number,\n needleLength: number,\n query: SearchQuery,\n): boolean {\n if (!query.ignoreWhitespace) {\n return !wordBefore(haystack.folded, at) && !wordAt(haystack.folded, at + needleLength);\n }\n const { start, length } = toOriginalRange(haystack, at, needleLength);\n return !wordBefore(haystack.original, start) && !wordAt(haystack.original, start + length);\n}\n\n/**\n * All non-overlapping literal matches, in original code-unit space.\n * `haystack` must have been folded with `foldOptionsFor(query)`.\n */\nexport function matchLiteral(haystack: FoldedText, query: SearchQuery): SearchMatchRange[] {\n const needle = foldText(query.text, foldOptionsFor(query)).folded;\n // Nothing searchable: empty or whitespace-only needles would \"match\"\n // every collapsed space.\n if (needle.trim().length === 0) return [];\n\n const out: SearchMatchRange[] = [];\n let from = 0;\n while (from <= haystack.folded.length - needle.length) {\n const at = haystack.folded.indexOf(needle, from);\n if (at < 0) break;\n if (query.wholeWord && !isWholeWordHit(haystack, at, needle.length, query)) {\n from = at + 1;\n continue;\n }\n // Diacritic-sensitive folds are decomposed (base + marks), so a bare\n // needle would otherwise match just the base letters of an accented\n // char — \"cafe\" ending right before the U+0301 of \"café\". A match may\n // not end mid-character.\n if (query.matchDiacritics && at + needle.length < haystack.folded.length) {\n const after = haystack.folded.codePointAt(at + needle.length)!;\n if (MARK.test(String.fromCodePoint(after))) {\n from = at + 1;\n continue;\n }\n }\n out.push(toOriginalRange(haystack, at, needle.length));\n from = at + needle.length;\n }\n return out;\n}\n","import type { SearchMatchRange } from './fold';\nimport { wordAt, wordBefore } from './literal';\nimport type { SearchQuery } from './types';\n\n/**\n * The portable search-regex dialect: JavaScript `u`-mode syntax MINUS the\n * features RE2 refuses (backreferences, lookaround). The local engine\n * executes patterns with JS `RegExp`; the server executes the SAME\n * pattern with RE2, whose linear-time guarantee is the ReDoS defense.\n * Restricting both sides to the common subset keeps one query string\n * valid — and equally powerful — everywhere.\n */\nexport const SEARCH_REGEX_MAX_LENGTH = 512;\n\nexport type SearchRegexIssue = 'empty' | 'too-long' | 'backreference' | 'lookaround' | 'syntax';\n\nexport type SearchRegexValidation =\n | { ok: true }\n | { ok: false; issue: SearchRegexIssue; message: string };\n\n/**\n * Validate a pattern against the dialect. Cheap and dependency-free —\n * viewers call it on keystroke for early feedback; engines re-validate\n * and reject bad patterns with `InvalidArg`.\n */\nexport function validateSearchRegex(pattern: string): SearchRegexValidation {\n if (pattern.length === 0) {\n return { ok: false, issue: 'empty', message: 'Pattern is empty.' };\n }\n if (pattern.length > SEARCH_REGEX_MAX_LENGTH) {\n return {\n ok: false,\n issue: 'too-long',\n message: `Pattern exceeds ${SEARCH_REGEX_MAX_LENGTH} characters.`,\n };\n }\n\n // One pass tracking escape/char-class state: backreferences and\n // lookaround only mean what they mean outside a character class.\n let inClass = false;\n for (let i = 0; i < pattern.length; i++) {\n const ch = pattern[i];\n if (ch === '\\\\') {\n const next = pattern[i + 1] ?? '';\n if (!inClass && next >= '1' && next <= '9') {\n return {\n ok: false,\n issue: 'backreference',\n message: `Backreference \\\\${next} is not supported.`,\n };\n }\n if (!inClass && next === 'k' && pattern[i + 2] === '<') {\n return {\n ok: false,\n issue: 'backreference',\n message: 'Named backreferences (\\\\k<…>) are not supported.',\n };\n }\n i++; // consume the escaped char\n continue;\n }\n if (inClass) {\n if (ch === ']') inClass = false;\n continue;\n }\n if (ch === '[') {\n inClass = true;\n continue;\n }\n if (ch === '(' && pattern[i + 1] === '?') {\n const tag = pattern[i + 2] ?? '';\n if (tag === '=' || tag === '!') {\n return {\n ok: false,\n issue: 'lookaround',\n message: 'Lookahead ((?=…), (?!…)) is not supported.',\n };\n }\n // \"(?<\" is lookbehind when followed by = or !, a named GROUP otherwise.\n if (tag === '<' && (pattern[i + 3] === '=' || pattern[i + 3] === '!')) {\n return {\n ok: false,\n issue: 'lookaround',\n message: 'Lookbehind ((?<=…), (?<!…)) is not supported.',\n };\n }\n }\n }\n\n try {\n // `u` is the strict common ground with RE2's syntax; `m` because ^/$\n // meaning line boundaries is what page-text search wants.\n new RegExp(pattern, 'mu');\n } catch (error) {\n return { ok: false, issue: 'syntax', message: (error as Error).message };\n }\n return { ok: true };\n}\n\n/**\n * Every flag combination has DEFINED semantics — most by behavior, one by\n * loud rejection (see the {@link SearchQuery} table). The single validator\n * a UI needs: call it on keystroke to grey out the diacritics toggle in\n * regex mode and flag bad patterns early; engines run the same check and\n * reject with `InvalidArg`. Literal queries are always valid (an empty\n * literal simply finds nothing).\n */\nexport type SearchQueryIssue =\n | SearchRegexIssue\n | 'diacritics-with-regex'\n | 'ignore-whitespace-with-regex';\n\nexport type SearchQueryValidation =\n | { ok: true }\n | { ok: false; issue: SearchQueryIssue; message: string };\n\nexport function validateSearchQuery(query: SearchQuery): SearchQueryValidation {\n if (!query.regex) return { ok: true };\n if (query.matchDiacritics) {\n return {\n ok: false,\n issue: 'diacritics-with-regex',\n message:\n 'Diacritic-sensitive matching is not available for regex patterns (regex runs on the raw text plane).',\n };\n }\n if (query.ignoreWhitespace) {\n return {\n ok: false,\n issue: 'ignore-whitespace-with-regex',\n message:\n 'Whitespace-insensitive matching is not available for regex patterns (regex runs on the raw text plane; use \\\\s* in the pattern).',\n };\n }\n return validateSearchRegex(query.text);\n}\n\n/**\n * All matches of a dialect-valid pattern over the RAW page text (regex\n * does not run against folded text — case handling is the `i` flag, and\n * diacritic folding never applies). `wholeWord` is a boundary POST-FILTER\n * using the same Unicode word test as the literal path — never `\\b`,\n * whose ASCII word set would give the toggle different semantics in regex\n * mode (\"caf\" whole-word matching inside \"café\"). Filtering after the\n * match also survives the move to RE2 server-side. Zero-length matches\n * are skipped: search UI cannot highlight nothing, and skipping them is\n * also the infinite-loop guard for patterns like `a*`.\n */\nexport function matchRegex(text: string, query: SearchQuery): SearchMatchRange[] {\n const valid = validateSearchQuery({ ...query, regex: true });\n if (!valid.ok) throw new Error(`Invalid search query (${valid.issue}): ${valid.message}`);\n\n const re = new RegExp(query.text, query.matchCase ? 'gmu' : 'gimu');\n const out: SearchMatchRange[] = [];\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n if (m[0].length === 0) {\n // Advance one full code point past the empty match.\n const unit = text.charCodeAt(re.lastIndex);\n re.lastIndex += unit >= 0xd800 && unit <= 0xdbff ? 2 : 1;\n continue;\n }\n if (query.wholeWord && (wordBefore(text, m.index) || wordAt(text, m.index + m[0].length))) {\n continue;\n }\n out.push({ start: m.index, length: m[0].length });\n }\n return out;\n}\n","import { foldText } from './fold';\nimport type { SearchMatchRange } from './fold';\nimport { foldOptionsFor, matchLiteral } from './literal';\nimport { matchRegex } from './regex';\nimport type { SearchQuery } from './types';\n\n/**\n * The whole match stage in one pure call: page text in, original-space\n * match ranges out. Engines with a pre-folded corpus for the default fold\n * skip this and call `matchLiteral` on the cached `FoldedText` directly;\n * everything else (non-default fold options, regex, tests) comes through\n * here.\n */\nexport function matchPageText(text: string, query: SearchQuery): SearchMatchRange[] {\n if (query.regex) return matchRegex(text, query);\n return matchLiteral(foldText(text, foldOptionsFor(query)), query);\n}\n","import type { SearchMatchRange } from './fold';\nimport type { SearchSnippet } from './types';\n\n/** Default context on each side of a match, in code units. */\nexport const SEARCH_SNIPPET_CONTEXT = 48;\n\nconst WHITESPACE = /\\s/;\n// Length-preserving: every whitespace unit becomes one plain space, so\n// `matchStart`/`matchLength` stay valid offsets into the flattened text.\nconst WHITESPACE_ALL = /\\s/g;\n\nconst isLowSurrogate = (text: string, index: number): boolean => {\n const unit = text.charCodeAt(index);\n return unit >= 0xdc00 && unit <= 0xdfff;\n};\n\n/**\n * The `'full'`-mode excerpt around one match: up to `context` code units\n * of page text on each side, trimmed to a whitespace boundary when one\n * exists inside the window (so snippets start and end on whole words),\n * never splitting a surrogate pair, whitespace flattened 1:1.\n */\nexport function buildSnippet(\n text: string,\n range: SearchMatchRange,\n context: number = SEARCH_SNIPPET_CONTEXT,\n): SearchSnippet {\n const matchEnd = range.start + range.length;\n\n let start = Math.max(0, range.start - context);\n if (start > 0) {\n // Cut at the first whitespace inside the leading context, if any —\n // otherwise accept the mid-word cut (one very long token).\n for (let i = start; i < range.start; i++) {\n if (WHITESPACE.test(text[i])) {\n start = i + 1;\n break;\n }\n }\n if (isLowSurrogate(text, start)) start++;\n }\n\n let end = Math.min(text.length, matchEnd + context);\n if (end < text.length) {\n for (let i = end - 1; i >= matchEnd; i--) {\n if (WHITESPACE.test(text[i])) {\n end = i;\n break;\n }\n }\n if (isLowSurrogate(text, end)) end--;\n }\n\n return {\n text: text.slice(start, end).replace(WHITESPACE_ALL, ' '),\n matchStart: range.start - start,\n matchLength: range.length,\n };\n}\n","import {\n isRotatedGeometryRun,\n type PageGeometrySnapshot,\n type RotatedGeometryRun,\n} from '../dto/PageGeometrySnapshot';\nimport type { PdfPoint, PdfQuad, PdfRect } from '../geometry/primitives';\n\n/**\n * The canonical text-interaction layout — the ONE place glyph geometry\n * becomes hit targets, word/line ranges, and visual-line segments.\n *\n * Selection owns gestures and state; search owns matching and cursors;\n * NEITHER owns segmentation. Both consume this module, so a text range has\n * exactly one canonical segmentation regardless of how it was produced, and\n * coordinate conversion (PDF → content/view) happens strictly afterward at\n * the plugin seam.\n *\n * Everything here is PDF user space (y-up), the engine's one geometry\n * vocabulary. The line-merge is adapted from Chromium's\n * pdf/pdfium/pdfium_range.cc `MergeAdjacentRects` (BSD-licensed, Copyright\n * 2010 The Chromium Authors); hit-testing mirrors PDFium `GetIndexAtPos`\n * (exact tight box first, then a tolerance pass).\n *\n * ORIENTATION MODEL — frames. Every run belongs to a FRAME: frame 0 is page\n * space itself (all upright runs — the dominant case takes a byte-identical\n * fast path), and each rotated orientation cluster gets an orthonormal frame\n * in which its text reads upright (baseline +x, ascent +y). Frames are\n * derived from the SEMANTIC EDGES of the first classifiable glyph's quad —\n * never from advisory wire fields — and keyed by (baseline direction,\n * ascent handedness):\n *\n * - Rotated and mirrored text become upright inside their frame.\n * - Shear (fake italic) is deliberately NOT part of the frame key or the\n * basis: a sheared run shares the frame of its unsheared neighbours, so\n * a mixed roman/italic line merges into ONE segment (Acrobat parity),\n * and the shear is absorbed as a small in-frame AABB residue. This is\n * the deterministic, order-independent contract — an affine\n * (shear-preserving) basis would either fragment mixed lines or make\n * the roman body's geometry depend on whether an italic run came first.\n * - Runs of different frames never merge into one line.\n *\n * All algorithms run on frame-local boxes; every participating run of a\n * cluster is transformed through the SAME frame, so merged coordinates are\n * always commensurable. Only the output maps back to page space, as\n * oriented quads.\n */\n\nconst FLAG_SPACE = 1;\nconst FLAG_EMPTY = 2;\nconst isBoundary = (flags: number): boolean => (flags & (FLAG_SPACE | FLAG_EMPTY)) !== 0;\nconst isEmpty = (flags: number): boolean => (flags & FLAG_EMPTY) !== 0;\n\nconst CHAR_DISTANCE_FACTOR = 2.5;\nconst FONT_SIZE_RATIO_THRESHOLD = 1.5;\nconst VERTICAL_OVERLAP_THRESHOLD = 0.8;\nconst LINE_OVERLAP_THRESHOLD = 0.5;\n/** Baseline directions within ~0.5° share a frame. */\nconst FRAME_DOT_TOLERANCE = Math.cos(0.0087);\nconst EDGE_EPSILON = 1e-6;\n\n/**\n * One merged visual line of a text range, in PDF user space. `quad` is the\n * geometric authority (frame-geometric slot order: `p1..p4` = upper-start,\n * upper-end, lower-start, lower-end — visual semantics, NOT reading order);\n * `rect` is its axis-aligned bounds, produced by the same constructor.\n * `advance` is the READING direction along the baseline, derived from the\n * glyph SEQUENCE (+1 = the frame's +x), never inferred from geometry.\n */\nexport interface PdfTextSegment {\n quad: PdfQuad;\n rect: PdfRect;\n advance: 1 | -1;\n}\n\n/** One glyph in its frame's space. `loose` builds segments; `tight` hit-tests. */\nexport interface TextLayoutGlyph {\n loose: PdfRect;\n tight?: PdfRect;\n flags: number;\n}\n\n/** A contiguous run of glyphs (a text object) in one frame. */\nexport interface TextLayoutRun {\n /** First char index — identical to the flat glyph index (runs tile the page). */\n charStart: number;\n count: number;\n /** Frame-local loose box (page space itself in frame 0). */\n rect: PdfRect;\n fontSize?: number;\n /** Index into {@link PageTextLayout.frames}; 0 = page space (upright). */\n frame: number;\n}\n\n/** An orientation cluster's orthonormal basis in page space. */\nexport interface TextLayoutFrame {\n /** Unit vector along the reading baseline (+x of the frame). */\n baseline: PdfPoint;\n /** Unit vector toward the ascent side (+y of the frame), ⟂ baseline. */\n ascent: PdfPoint;\n}\n\n/**\n * A page's text laid out per-frame: a flat glyph list (index = text-page\n * char index), the run structure, and the orientation frames.\n */\nexport interface PageTextLayout {\n glyphs: TextLayoutGlyph[];\n runs: TextLayoutRun[];\n frames: TextLayoutFrame[];\n}\n\nconst IDENTITY_FRAME: TextLayoutFrame = { baseline: { x: 1, y: 0 }, ascent: { x: 0, y: 1 } };\n\nconst toFrame = (f: TextLayoutFrame, p: PdfPoint): PdfPoint => ({\n x: p.x * f.baseline.x + p.y * f.baseline.y,\n y: p.x * f.ascent.x + p.y * f.ascent.y,\n});\n\nconst fromFrame = (f: TextLayoutFrame, p: PdfPoint): PdfPoint => ({\n x: f.baseline.x * p.x + f.ascent.x * p.y,\n y: f.baseline.y * p.x + f.ascent.y * p.y,\n});\n\nconst ZERO_RECT: PdfRect = { left: 0, bottom: 0, right: 0, top: 0 };\n\n/** Frame-local AABB of a page-space cell (exact under the frame's rotation;\n * shear residue is the documented in-frame envelope). */\nfunction frameBoxOfQuad(f: TextLayoutFrame, q: PdfQuad): PdfRect {\n const pts = [q.p1, q.p2, q.p3, q.p4].map((p) => toFrame(f, p));\n const xs = pts.map((p) => p.x);\n const ys = pts.map((p) => p.y);\n return {\n left: Math.min(...xs),\n bottom: Math.min(...ys),\n right: Math.max(...xs),\n top: Math.max(...ys),\n };\n}\n\n/** Find-or-create the frame for a rotated run, keyed by the baseline\n * direction + ascent handedness of its first classifiable glyph's edges. */\nfunction frameForRun(frames: TextLayoutFrame[], run: RotatedGeometryRun): number {\n const seed = run.glyphs.find((g) => !isEmpty(g.flags));\n if (!seed) return 0;\n const q = seed.looseQuad;\n const bx = q.p2.x - q.p1.x;\n const by = q.p2.y - q.p1.y;\n const len = Math.hypot(bx, by);\n if (len <= EDGE_EPSILON) return 0;\n const baseline: PdfPoint = { x: bx / len, y: by / len };\n // Handedness from the actual ascent edge (lower-start → upper-start), so\n // mirrored text gets its own frame with \"up\" on its true ascent side.\n const ax = q.p1.x - q.p3.x;\n const ay = q.p1.y - q.p3.y;\n const sign = baseline.x * ay - baseline.y * ax >= 0 ? 1 : -1;\n const ascent: PdfPoint = { x: -baseline.y * sign, y: baseline.x * sign };\n\n for (let i = 0; i < frames.length; i++) {\n const f = frames[i];\n const dot = f.baseline.x * baseline.x + f.baseline.y * baseline.y;\n const sameHandedness = f.ascent.x * ascent.x + f.ascent.y * ascent.y > 0;\n if (dot >= FRAME_DOT_TOLERANCE && sameHandedness) return i;\n }\n frames.push({ baseline, ascent });\n return frames.length - 1;\n}\n\n/**\n * Flatten a page's geometry snapshot into the canonical layout. Upright runs\n * copy their wire boxes verbatim (frame 0 — byte-identical to the\n * pre-orientation behavior, wire run rects included); rotated runs project\n * their glyph cells into their cluster's frame.\n */\nexport function buildPageTextLayout(snapshot: PageGeometrySnapshot): PageTextLayout {\n const glyphs: TextLayoutGlyph[] = [];\n const runs: TextLayoutRun[] = [];\n const frames: TextLayoutFrame[] = [IDENTITY_FRAME];\n\n for (const run of snapshot.runs) {\n if (!isRotatedGeometryRun(run)) {\n for (const g of run.glyphs) {\n glyphs.push({ loose: g.looseBox, tight: g.tightBox, flags: g.flags });\n }\n runs.push({\n charStart: run.charStart,\n count: run.glyphs.length,\n rect: run.rect,\n fontSize: run.fontSize,\n frame: 0,\n });\n continue;\n }\n\n const frame = frameForRun(frames, run);\n const f = frames[frame];\n let runBox: PdfRect | null = null;\n for (const g of run.glyphs) {\n if (isEmpty(g.flags)) {\n glyphs.push({ loose: ZERO_RECT, flags: g.flags });\n continue;\n }\n const loose = frameBoxOfQuad(f, g.looseQuad);\n const tight = g.tightQuad ? frameBoxOfQuad(f, g.tightQuad) : undefined;\n glyphs.push({ loose, tight, flags: g.flags });\n runBox = runBox\n ? {\n left: Math.min(runBox.left, loose.left),\n bottom: Math.min(runBox.bottom, loose.bottom),\n right: Math.max(runBox.right, loose.right),\n top: Math.max(runBox.top, loose.top),\n }\n : loose;\n }\n runs.push({\n charStart: run.charStart,\n count: run.glyphs.length,\n rect: runBox ?? ZERO_RECT,\n fontSize: run.fontSize,\n frame,\n });\n }\n return { glyphs, runs, frames };\n}\n\nconst inRect = (r: PdfRect, p: PdfPoint): boolean =>\n p.x >= r.left && p.x <= r.right && p.y >= r.bottom && p.y <= r.top;\n\nfunction avgGlyphHeight(layout: PageTextLayout): number {\n let total = 0;\n let count = 0;\n for (const g of layout.glyphs) {\n if (isEmpty(g.flags)) continue;\n total += g.loose.top - g.loose.bottom;\n count++;\n }\n return count === 0 ? 0 : total / count;\n}\n\n/** The point expressed in every frame (index-aligned with `layout.frames`).\n * Frame 0 returns the point itself — no float round-trip on the fast path. */\nfunction pointPerFrame(layout: PageTextLayout, p: PdfPoint): PdfPoint[] {\n return layout.frames.map((f, i) => (i === 0 ? p : toFrame(f, p)));\n}\n\n/**\n * The glyph (char) index at a page-space point, or null when nothing is near\n * (so callers can show the pointer cursor off-text). PDFium `GetIndexAtPos`:\n * exact tight-box containment first, then a tolerance pass (closest by\n * Manhattan distance within `toleranceFactor × average glyph height`). Each\n * run tests the point in ITS OWN frame, so rotated text hit-tests exactly.\n */\nexport function textGlyphAt(\n layout: PageTextLayout,\n point: PdfPoint,\n toleranceFactor = 1.5,\n): number | null {\n const pts = pointPerFrame(layout, point);\n for (const run of layout.runs) {\n const q = pts[run.frame];\n if (!inRect(run.rect, q)) continue;\n for (let i = 0; i < run.count; i++) {\n const g = layout.glyphs[run.charStart + i];\n if (inRect(g.tight ?? g.loose, q)) return run.charStart + i;\n }\n }\n if (toleranceFactor <= 0) return null;\n\n const half = (avgGlyphHeight(layout) * toleranceFactor) / 2;\n let best = -1;\n let bestDist = Infinity;\n for (const run of layout.runs) {\n const q = pts[run.frame];\n const r = run.rect;\n if (\n q.x < r.left - half ||\n q.x > r.right + half ||\n q.y < r.bottom - half ||\n q.y > r.top + half\n ) {\n continue;\n }\n for (let i = 0; i < run.count; i++) {\n const g = layout.glyphs[run.charStart + i];\n if (isEmpty(g.flags)) continue;\n const b = g.tight ?? g.loose;\n if (\n q.x < b.left - half ||\n q.x > b.right + half ||\n q.y < b.bottom - half ||\n q.y > b.top + half\n ) {\n continue;\n }\n const dx = Math.min(Math.abs(q.x - b.left), Math.abs(q.x - b.right));\n const dy = Math.min(Math.abs(q.y - b.bottom), Math.abs(q.y - b.top));\n if (dx + dy < bestDist) {\n bestDist = dx + dy;\n best = run.charStart + i;\n }\n }\n }\n return best >= 0 ? best : null;\n}\n\n/** Double-click: the word around `glyph` (walk to space/empty glyphs both ways). */\nexport function expandTextRangeToWord(layout: PageTextLayout, glyph: number): [number, number] {\n const n = layout.glyphs.length;\n if (glyph < 0 || glyph >= n) return [glyph, glyph];\n let from = glyph;\n while (from > 0 && !isBoundary(layout.glyphs[from - 1].flags)) from--;\n let to = glyph;\n while (to < n - 1 && !isBoundary(layout.glyphs[to + 1].flags)) to++;\n return [from, to];\n}\n\n/** Triple-click: the full visual line — SAME-FRAME runs whose vertical extent\n * overlaps the anchor run's. A differently-oriented run is a line boundary. */\nexport function expandTextRangeToLine(layout: PageTextLayout, glyph: number): [number, number] {\n const ri = layout.runs.findIndex((r) => glyph >= r.charStart && glyph < r.charStart + r.count);\n if (ri < 0) return [glyph, glyph];\n const anchor = layout.runs[ri];\n const bottom = anchor.rect.bottom;\n const top = anchor.rect.top;\n let from = anchor.charStart;\n let to = anchor.charStart + anchor.count - 1;\n for (let r = ri - 1; r >= 0; r--) {\n const run = layout.runs[r];\n if (isZero(run.rect)) continue;\n if (run.frame !== anchor.frame) break;\n if (!overlapV(run.rect.bottom, run.rect.top, bottom, top)) break;\n from = run.charStart;\n }\n for (let r = ri + 1; r < layout.runs.length; r++) {\n const run = layout.runs[r];\n if (isZero(run.rect)) continue;\n if (run.frame !== anchor.frame) break;\n if (!overlapV(run.rect.bottom, run.rect.top, bottom, top)) break;\n to = run.charStart + run.count - 1;\n }\n return [from, to];\n}\n\n/**\n * A single glyph's oriented cell in page space, or null for degenerate\n * glyphs — the anchor for caret placement at a selection boundary.\n */\nexport function textGlyphQuad(layout: PageTextLayout, glyph: number): PdfQuad | null {\n const g = layout.glyphs[glyph];\n if (!g || isEmpty(g.flags)) return null;\n const b = g.loose;\n if (b.right <= b.left || b.top <= b.bottom) return null;\n const run = layout.runs.find((r) => glyph >= r.charStart && glyph < r.charStart + r.count);\n const f = layout.frames[run?.frame ?? 0];\n return quadOfFrameRect(f, run?.frame ?? 0, b);\n}\n\ninterface SubRun {\n rect: PdfRect;\n charCount: number;\n fontSize?: number;\n frame: number;\n /** Baseline x of the FIRST/LAST glyph in sequence order (frame space) —\n * the reading-direction signal. */\n firstX: number;\n lastX: number;\n}\n\n/**\n * Merged visual-line segments for the half-open char range\n * `[charStart, charStart + charCount)` — THE canonical segmentation. Chars\n * outside the layout are ignored.\n */\nexport function textSegmentsForRange(\n layout: PageTextLayout,\n charStart: number,\n charCount: number,\n): PdfTextSegment[] {\n if (charCount <= 0 || layout.glyphs.length === 0) return [];\n const lo = Math.max(0, charStart);\n const hi = Math.min(layout.glyphs.length - 1, charStart + charCount - 1);\n if (hi < lo) return [];\n const subRuns: SubRun[] = [];\n\n for (const run of layout.runs) {\n const runEnd = run.charStart + run.count - 1;\n if (runEnd < lo || run.charStart > hi) continue;\n const s = Math.max(lo, run.charStart);\n const e = Math.min(hi, runEnd);\n\n let left = Infinity;\n let right = -Infinity;\n let bottom = Infinity;\n let top = -Infinity;\n let charCountAcc = 0;\n let widthSum = 0;\n let prevRight = -Infinity;\n let firstX = 0;\n let lastX = 0;\n const flush = () => {\n if (charCountAcc > 0 && left !== Infinity) {\n subRuns.push({\n rect: { left, bottom, right, top },\n charCount: charCountAcc,\n fontSize: run.fontSize,\n frame: run.frame,\n firstX,\n lastX,\n });\n }\n left = Infinity;\n right = -Infinity;\n bottom = Infinity;\n top = -Infinity;\n charCountAcc = 0;\n widthSum = 0;\n prevRight = -Infinity;\n };\n\n for (let ci = s; ci <= e; ci++) {\n const g = layout.glyphs[ci];\n if (isEmpty(g.flags)) continue;\n const b = g.loose;\n if (charCountAcc > 0 && prevRight > -Infinity) {\n const avg = widthSum / charCountAcc;\n if (avg > 0 && Math.abs(b.left - prevRight) > CHAR_DISTANCE_FACTOR * avg) flush();\n }\n const centerX = (b.left + b.right) / 2;\n if (charCountAcc === 0) firstX = centerX;\n lastX = centerX;\n left = Math.min(left, b.left);\n right = Math.max(right, b.right);\n bottom = Math.min(bottom, b.bottom);\n top = Math.max(top, b.top);\n charCountAcc++;\n widthSum += b.right - b.left;\n prevRight = b.right;\n }\n flush();\n }\n\n return mergeAdjacentSubRuns(subRuns).map((m) => materializeSegment(layout, m));\n}\n\ninterface MergedSubRun {\n rect: PdfRect;\n frame: number;\n firstX: number;\n lastX: number;\n}\n\nfunction mergeAdjacentSubRuns(runs: SubRun[]): MergedSubRun[] {\n const out: MergedSubRun[] = [];\n let prev: SubRun | null = null;\n let cur: MergedSubRun | null = null;\n for (const run of runs) {\n // Frames are canonical per cluster, so index equality IS the \"same\n // orientation\" test — every participant was projected through the SAME\n // frame, keeping merged coordinates commensurable.\n if (prev && cur && prev.frame === run.frame && shouldMerge(prev, run)) {\n cur = {\n rect: {\n left: Math.min(cur.rect.left, run.rect.left),\n bottom: Math.min(cur.rect.bottom, run.rect.bottom),\n right: Math.max(cur.rect.right, run.rect.right),\n top: Math.max(cur.rect.top, run.rect.top),\n },\n frame: cur.frame,\n firstX: cur.firstX,\n lastX: run.lastX,\n };\n } else {\n if (cur) out.push(cur);\n cur = { rect: run.rect, frame: run.frame, firstX: run.firstX, lastX: run.lastX };\n }\n prev = run;\n }\n if (cur && cur.rect.right > cur.rect.left && cur.rect.top > cur.rect.bottom) out.push(cur);\n return out;\n}\n\n/** Segment quad for a frame-local rect (frame 0: the rect's own corners,\n * no float round-trip). Slot order US, UE, LS, LE; frame is y-up, so the\n * upper corners sit at the frame TOP. */\nfunction quadOfFrameRect(f: TextLayoutFrame, frameIndex: number, r: PdfRect): PdfQuad {\n if (frameIndex === 0) {\n return {\n p1: { x: r.left, y: r.top },\n p2: { x: r.right, y: r.top },\n p3: { x: r.left, y: r.bottom },\n p4: { x: r.right, y: r.bottom },\n };\n }\n return {\n p1: fromFrame(f, { x: r.left, y: r.top }),\n p2: fromFrame(f, { x: r.right, y: r.top }),\n p3: fromFrame(f, { x: r.left, y: r.bottom }),\n p4: fromFrame(f, { x: r.right, y: r.bottom }),\n };\n}\n\nfunction materializeSegment(layout: PageTextLayout, m: MergedSubRun): PdfTextSegment {\n const frame = layout.frames[m.frame];\n const quad = quadOfFrameRect(frame, m.frame, m.rect);\n const rect =\n m.frame === 0\n ? m.rect\n : {\n left: Math.min(quad.p1.x, quad.p2.x, quad.p3.x, quad.p4.x),\n bottom: Math.min(quad.p1.y, quad.p2.y, quad.p3.y, quad.p4.y),\n right: Math.max(quad.p1.x, quad.p2.x, quad.p3.x, quad.p4.x),\n top: Math.max(quad.p1.y, quad.p2.y, quad.p3.y, quad.p4.y),\n };\n return { quad, rect, advance: m.lastX >= m.firstX ? 1 : -1 };\n}\n\nfunction shouldMerge(a: SubRun, b: SubRun): boolean {\n if (a.fontSize != null && b.fontSize != null && a.fontSize > 0 && b.fontSize > 0) {\n const ratio = Math.max(a.fontSize, b.fontSize) / Math.min(a.fontSize, b.fontSize);\n if (ratio > FONT_SIZE_RATIO_THRESHOLD) return false;\n }\n if (verticalOverlap(a.rect, b.rect) < VERTICAL_OVERLAP_THRESHOLD) return false;\n const aw = (a.rect.right - a.rect.left) / a.charCount;\n const bw = (b.rect.right - b.rect.left) / b.charCount;\n const aL = a.rect.left - aw;\n const aR = a.rect.right + aw;\n const bL = b.rect.left - bw;\n const bR = b.rect.right + bw;\n return aL < bR && aR > bL;\n}\n\nfunction verticalOverlap(a: PdfRect, b: PdfRect): number {\n const ah = a.top - a.bottom;\n const bh = b.top - b.bottom;\n if (ah <= 0 || bh <= 0) return 0;\n const u = Math.max(a.top, b.top) - Math.min(a.bottom, b.bottom);\n if (u === ah || u === bh) return 1;\n const i = Math.max(0, Math.min(a.top, b.top) - Math.max(a.bottom, b.bottom));\n return i / u;\n}\n\nconst isZero = (r: PdfRect): boolean => r.right === r.left && r.top === r.bottom;\n\nfunction overlapV(bottom1: number, top1: number, bottom2: number, top2: number): boolean {\n const u = Math.max(top1, top2) - Math.min(bottom1, bottom2);\n if (u === 0) return false;\n const i = Math.max(0, Math.min(top1, top2) - Math.max(bottom1, bottom2));\n return i / u >= LINE_OVERLAP_THRESHOLD;\n}\n","import type { PageGeometrySnapshot } from '../dto/PageGeometrySnapshot';\nimport type { PdfRect } from '../geometry/primitives';\nimport { buildPageTextLayout, textSegmentsForRange, type PdfTextSegment } from '../text/layout';\n\n/**\n * Match-range → canonical visual-line segments. Thin wrappers over the ONE\n * text layout (`src/text/layout.ts`) — search owns matching and cursors,\n * never segmentation, so a match highlights exactly like a selection of the\n * same characters. No frame or merge logic lives here.\n */\n\n/** Canonical segments for `[charStart, charStart + charCount)`. */\nexport function searchSegmentsForRange(\n snapshot: PageGeometrySnapshot,\n charStart: number,\n charCount: number,\n): PdfTextSegment[] {\n return textSegmentsForRange(buildPageTextLayout(snapshot), charStart, charCount);\n}\n\n/** The segments' AABBs — for consumers that genuinely want boxes. */\nexport function searchRectsForRange(\n snapshot: PageGeometrySnapshot,\n charStart: number,\n charCount: number,\n): PdfRect[] {\n return searchSegmentsForRange(snapshot, charStart, charCount).map((s) => s.rect);\n}\n","import type { DocumentManifest } from '../dto/DocumentManifest';\nimport { foldText } from './fold';\nimport type { SearchQuery } from './types';\n\n/**\n * The search CONTENT EPOCH: a deterministic fingerprint of everything a\n * search result depends on — page order/structure (`layoutVersion`) and\n * each page's text content (`contentVersion`), nothing else. Annotation\n * and metadata churn deliberately do NOT move it, so cached search\n * responses in a collaborative document survive comment storms.\n *\n * Both sides compute it from the manifest they already hold: the client\n * to mint versioned search URLs, the server to validate them (mismatch →\n * NotFound, the standard stale-versioned-read signal). FNV-1a 64-bit —\n * dependency-free and stable; not cryptographic, and doesn't need to be:\n * an adversary can only vary his OWN authorized query results.\n */\nexport function searchContentEpoch(manifest: DocumentManifest): string {\n let input = `${manifest.layoutVersion}`;\n for (const page of manifest.pages) {\n input += `|${page.state.pageObjectNumber}:${page.cache.contentVersion}`;\n }\n return fnv1a64(input);\n}\n\nconst FNV_OFFSET = 0xcbf29ce484222325n;\nconst FNV_PRIME = 0x100000001b3n;\nconst MASK_64 = 0xffffffffffffffffn;\n\nfunction fnv1a64(input: string): string {\n let hash = FNV_OFFSET;\n for (let i = 0; i < input.length; i++) {\n hash ^= BigInt(input.charCodeAt(i));\n hash = (hash * FNV_PRIME) & MASK_64;\n }\n return hash.toString(16).padStart(16, '0');\n}\n\n/**\n * Canonicalize a query for CACHE KEYING: default-fold literal queries are\n * pre-folded (\"Café\", \"café\" and \"CAFE\" are the same search, so they\n * should be the same cache entry). Semantics are unchanged — the fold is\n * idempotent and exactly what the matcher applies to the needle anyway.\n * Case- or diacritic-sensitive literals and regex patterns pass through\n * untouched (their raw form IS the query).\n */\nexport function canonicalSearchQuery(query: SearchQuery): SearchQuery {\n if (query.regex || query.matchCase || query.matchDiacritics || query.ignoreWhitespace) {\n return query;\n }\n const canonical: SearchQuery = { text: foldText(query.text).folded };\n if (query.wholeWord) canonical.wholeWord = true;\n return canonical;\n}\n","import type { PdfBits } from './types';\n\n/**\n * ISO 32000 user-access permission bit positions, expressed as integer\n * masks. Bit numbers in the spec are 1-indexed, so bit 3 = `1 << 2`.\n *\n * Bits 1, 2, 7, 8, and 13+ are reserved and not surfaced here.\n */\nexport const PDF_BITS = {\n /** Bit 3 — print the document. */\n PRINT: 1 << 2,\n /** Bit 4 — modify content streams. */\n MODIFY: 1 << 3,\n /** Bit 5 — copy/extract text and graphics. */\n COPY: 1 << 4,\n /** Bit 6 — annotate + fill forms (+ modify form fields with bit 4). */\n ANNOTATE_FILL: 1 << 5,\n /** Bit 9 — fill existing forms (even if bit 6 is clear). */\n FILL_FORMS: 1 << 8,\n /** Bit 10 — accessibility extraction (deprecated in PDF 2.0). */\n ACCESSIBILITY: 1 << 9,\n /** Bit 11 — assemble document (insert/rotate/delete pages, outline). */\n ASSEMBLE: 1 << 10,\n /** Bit 12 — high-quality print (refines bit 3). */\n PRINT_HIGH: 1 << 11,\n} as const;\n\n/**\n * Decode a raw PDFium permission integer into a typed boolean view.\n *\n * `null` input (the documents row column is nullable until probed)\n * yields all-false bits — i.e., a maximally restrictive interpretation.\n * That keeps `pdf.permissions` expansion safe on unprobed documents.\n */\nexport function decodePdfBits(raw: number | null): PdfBits {\n if (raw === null) {\n return {\n bit3: false,\n bit4: false,\n bit5: false,\n bit6: false,\n bit9: false,\n bit10: false,\n bit11: false,\n bit12: false,\n };\n }\n return {\n bit3: (raw & PDF_BITS.PRINT) !== 0,\n bit4: (raw & PDF_BITS.MODIFY) !== 0,\n bit5: (raw & PDF_BITS.COPY) !== 0,\n bit6: (raw & PDF_BITS.ANNOTATE_FILL) !== 0,\n bit9: (raw & PDF_BITS.FILL_FORMS) !== 0,\n bit10: (raw & PDF_BITS.ACCESSIBILITY) !== 0,\n bit11: (raw & PDF_BITS.ASSEMBLE) !== 0,\n bit12: (raw & PDF_BITS.PRINT_HIGH) !== 0,\n };\n}\n","import type { DocCapability, PdfBits } from './types';\n\n/**\n * Typed capability constants for customer-side JWT minting.\n *\n * The shape mirrors the dotted capability name so it reads naturally:\n * caps.doc.text.copy() // \"doc.text.copy\"\n * caps.doc.download() // \"doc.download\"\n * caps.doc.download.flattened() // \"doc.download.flattened\"\n * caps.doc.print.high() // \"doc.print.high\"\n *\n * Each leaf is a function returning the literal string (as `const`) so\n * TypeScript catches typos at the call site. Wrappers like `download`\n * and `print` are `Object.assign`'d to be callable AND carry child\n * properties for the refinement capabilities.\n */\nexport const caps = {\n doc: {\n open: () => 'doc.open' as const,\n render: () => 'doc.render' as const,\n text: {\n select: () => 'doc.text.select' as const,\n copy: () => 'doc.text.copy' as const,\n search: () => 'doc.text.search' as const,\n },\n content: {\n copy: () => 'doc.content.copy' as const,\n },\n download: Object.assign(() => 'doc.download' as const, {\n flattened: () => 'doc.download.flattened' as const,\n }),\n print: Object.assign(() => 'doc.print' as const, {\n high: () => 'doc.print.high' as const,\n }),\n pages: {\n modify: () => 'doc.pages.modify' as const,\n assemble: () => 'doc.pages.assemble' as const,\n },\n forms: {\n read: () => 'doc.forms.read' as const,\n fill: () => 'doc.forms.fill' as const,\n modify: () => 'doc.forms.modify' as const,\n },\n annotate: {\n read: () => 'doc.annotate.read' as const,\n modify: () => 'doc.annotate.modify' as const,\n },\n metadata: {\n modify: () => 'doc.metadata.modify' as const,\n },\n attachments: {\n modify: () => 'doc.attachments.modify' as const,\n },\n redact: () => 'doc.redact' as const,\n },\n} as const;\n\n/**\n * Builder factory for collab scope filters. Each entity:action pair\n * gets a sub-object with the four filter constructors.\n *\n * collab.annotations.create.self() → \"annotations:create:self\"\n * collab.annotations.create.group(\"legal\") → \"annotations:create:group=legal\"\n * collab.annotations.update.group(\"4\") → \"annotations:update:group=4\"\n * collab.annotations.delete.createdBy(\"u-7\") → \"annotations:delete:createdBy=u-7\"\n * collab.annotations.setGroup.group(\"legal\") → \"annotations:set-group:group=legal\"\n * collab.annotations.all.all() → \"annotations:*:all\" (action wildcard)\n *\n * On create, the filter is evaluated against the caller's own identity\n * (no impersonation), so `:self` and `:all` trivially pass; `:group=X`\n * is the meaningful filter — it constrains creation to callers whose\n * default group is X.\n */\nexport const collab = {\n annotations: {\n create: makeFilterBuilder('annotations', 'create'),\n update: makeFilterBuilder('annotations', 'update'),\n delete: makeFilterBuilder('annotations', 'delete'),\n setGroup: makeSetGroupBuilder(),\n /** Action wildcard — matches create, update, delete, AND set-group with the given filter. */\n all: makeFilterBuilder('annotations', '*'),\n },\n} as const;\n\ninterface FilterBuilder {\n all(): string;\n self(): string;\n createdBy(userId: string): string;\n group(groupId: string): string;\n}\n\nfunction makeFilterBuilder(entity: string, action: string): FilterBuilder {\n return {\n all: () => `${entity}:${action}:all`,\n self: () => `${entity}:${action}:self`,\n createdBy: (userId: string) => `${entity}:${action}:createdBy=${userId}`,\n group: (groupId: string) => `${entity}:${action}:group=${groupId}`,\n };\n}\n\n/**\n * `set-group` is an authority filter, not a per-record collab filter:\n * only `:all` and `:group=X` are meaningful (assign-to-any vs\n * assign-to-X). The builder exposes exactly those two — a typo at JWT\n * mint time is caught by the compiler instead of producing a JWT that\n * fails at verify.\n */\ninterface SetGroupBuilder {\n all(): string;\n group(groupId: string): string;\n}\n\nfunction makeSetGroupBuilder(): SetGroupBuilder {\n return {\n all: () => 'annotations:set-group:all',\n group: (groupId: string) => `annotations:set-group:group=${groupId}`,\n };\n}\n\n/**\n * Builder for the `pdf.permissions` virtual scope. Returns the literal\n * string; provided as a helper for parity with caps/collab in JWT\n * construction code.\n */\nexport const pdfPermissions = (): 'pdf.permissions' => 'pdf.permissions';\n\n/**\n * Materialise `pdf.permissions` into the concrete capability list it\n * would expand to under the given PDF bit configuration.\n *\n * Useful when the customer wants to start from PDF defaults and then\n * subtract specific capabilities — easier to build the JWT scope array\n * by filtering an explicit list than by composing virtual + denials.\n *\n * const defaults = materializePdfPermissions(pdfBits);\n * const scope = [\n * ...defaults.filter(s => s !== 'doc.text.copy'),\n * 'doc.download',\n * ];\n *\n * IMPORTANT: this MUST stay in sync with `addPdfPermissions` inside\n * resolver.ts. A test pins them together.\n */\nexport function materializePdfPermissions(b: PdfBits): DocCapability[] {\n const out = new Set<DocCapability>();\n\n // Always — pdf.permissions means \"give me a working session\"\n out.add('doc.open');\n out.add('doc.render');\n // Reading existing annotations and form values is unconditional —\n // PDF bit 6 governs writes, not visibility.\n out.add('doc.annotate.read');\n out.add('doc.forms.read');\n\n if (b.bit5) {\n out.add('doc.text.select');\n out.add('doc.text.copy');\n out.add('doc.text.search');\n out.add('doc.content.copy');\n }\n if (b.bit3) out.add('doc.print');\n if (b.bit12 && b.bit3) out.add('doc.print.high');\n if (b.bit4) {\n out.add('doc.pages.modify');\n out.add('doc.redact');\n out.add('doc.metadata.modify');\n out.add('doc.attachments.modify');\n }\n if (b.bit11) out.add('doc.pages.assemble');\n if (b.bit6) out.add('doc.annotate.modify');\n if (b.bit6 || b.bit9) {\n out.add('doc.forms.fill');\n out.add('doc.sign');\n }\n if (b.bit6 && b.bit4) out.add('doc.forms.modify');\n\n return [...out];\n}\n","import type { PdfViewport } from '../dto/Measure';\nimport type { PdfPoint } from '../geometry/primitives';\n\n/** Last containing viewport wins. A foreign measure still wins; never guess a fallback. */\nexport function viewportForPoint<T extends PdfViewport>(\n viewports: readonly T[],\n point: PdfPoint,\n): T | undefined {\n return [...viewports]\n .reverse()\n .find(\n ({ bbox: b }) =>\n point.x >= b.left && point.x <= b.right && point.y >= b.bottom && point.y <= b.top,\n );\n}\n"],"mappings":"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"}
|