Address the pdf-auditor findings that survived the 2026-05-12 PDF stack overhaul (pdfme → react-pdf). Items C-2/C-3 (tiptap-to-pdfme bugs) were resolved when that 571-LOC bridge was deleted; remaining items: - **M-7 wrong-port brand fallback** — replace `'Port Nimara'` defaults in PDF-rendering services. `reports.service` and `expense-export` throw when the port row is missing (the job is FK-keyed on a real port, so absence = broken state, must not stamp a competitor brand). `record-export` uses `'(port)'` as the visible placeholder. - **M-2 silent field drift in fill-eoi-form** — promote the always-silent catch in `setText` / `setCheckbox` to log a structured warning per missing field (mirroring the existing `setBerthRange` pattern). A re-cut template with drifted AcroForm field names now surfaces in ops logs instead of shipping with empty values. - **M-3 form not flattened** — `fillEoiFormFields` now flattens the AcroForm before save. Documenso pathway flattens server-side; this brings the in-app pathway to parity, so the signer can't edit pre-filled yacht dimensions / address / berth number after the fact. - **M-1 PDF metadata** — set Title / Author / Subject / Lang / Producer / Creator on the generated EOI PDF for downstream readers and a11y tooling. - **M-4 noisy berth-range warnings** — downgrade per-mooring warn to debug; emit a single summary warn per call when any passthrough occurred. Multi-berth EOIs with archived/legacy moorings no longer spam the log on every render. - **M-6 source PDF sha pinning** — pin `assets/eoi-template.pdf` sha256 via `EXPECTED_EOI_SHA256` (exported for tests); `loadEoiTemplatePdf` warns once per process when the bytes drift without an explicit hash bump. Documented the intentional-update workflow in `assets/README.md`. Tests updated in `tests/unit/pdf/fill-eoi-form.test.ts` to reflect flatten + metadata (form fields are gone after flatten; pdf-lib has no getLanguage so we assert the other setters round-trip). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
70 lines
2.9 KiB
Markdown
70 lines
2.9 KiB
Markdown
# `assets/`
|
|
|
|
Server-side runtime assets bundled by Next.js (via `outputFileTracingIncludes`
|
|
in `next.config.ts`). These files are read with `fs.readFile` from
|
|
`process.cwd()` at runtime, so they are NOT served as public URLs — use
|
|
`public/` for that.
|
|
|
|
## `eoi-template.pdf`
|
|
|
|
The source PDF used by the in-app EOI generation pathway
|
|
(`src/lib/pdf/fill-eoi-form.ts`). It must be the **same** PDF that the
|
|
Documenso EOI template uploads, so both pathways produce equivalent
|
|
documents.
|
|
|
|
The PDF must contain AcroForm fields with these exact names (mirroring the
|
|
Documenso template's `formValues` keys — see
|
|
`docs/eoi-documenso-field-mapping.md`):
|
|
|
|
| Field name | Type | Filled with |
|
|
| -------------- | -------- | ----------------------------------------------------- |
|
|
| `Name` | Text | `EoiContext.client.fullName` |
|
|
| `Email` | Text | `EoiContext.client.primaryEmail` |
|
|
| `Address` | Text | `street, city, country` |
|
|
| `Yacht Name` | Text | `EoiContext.yacht.name` |
|
|
| `Length` | Text | `EoiContext.yacht.lengthFt` |
|
|
| `Width` | Text | `EoiContext.yacht.widthFt` |
|
|
| `Draft` | Text | `EoiContext.yacht.draftFt` |
|
|
| `Berth Number` | Text | `EoiContext.berth.mooringNumber` |
|
|
| `Lease_10` | Checkbox | always `false` (legacy default — Purchase, not Lease) |
|
|
| `Purchase` | Checkbox | always `true` |
|
|
|
|
The fill path **flattens** the AcroForm after writing values, so the
|
|
recipient can't edit pre-filled values (yacht dimensions, address, berth
|
|
number) after the fact. Documenso pathway flattens server-side; the
|
|
in-app pathway brings the artifact to parity.
|
|
|
|
### Expected sha256
|
|
|
|
The source PDF's sha256 is pinned to guard against silent template swaps
|
|
(an unreviewed asset swap would change legal output without a code diff):
|
|
|
|
```
|
|
ba495fd88d99ebe4b7f61acbe397fb2f1cd116e1e1f1b217de93106915c7c44b
|
|
```
|
|
|
|
`scripts/check-eoi-template-sha.ts` verifies this at boot of the in-app
|
|
pathway; the function exposes the expected hash via `EXPECTED_EOI_SHA256`
|
|
so tests can re-check after a deliberate template revision.
|
|
|
|
To intentionally update the template:
|
|
|
|
1. Drop the new PDF as `eoi-template.pdf`.
|
|
2. Run `shasum -a 256 assets/eoi-template.pdf`.
|
|
3. Update the hash in this README **and** in
|
|
`src/lib/pdf/fill-eoi-form.ts` (search for `EXPECTED_EOI_SHA256`).
|
|
|
|
### Override path
|
|
|
|
In dev/test, set `EOI_TEMPLATE_PDF_PATH=/abs/path/to/your/template.pdf` to
|
|
point at a different file (e.g. a fixture).
|
|
|
|
### How to extract this PDF
|
|
|
|
The legacy flow uploads this PDF to Documenso template ID 8. To get the
|
|
exact bytes:
|
|
|
|
1. In Documenso, open the EOI template.
|
|
2. Download the source PDF.
|
|
3. Drop it here as `eoi-template.pdf`.
|