--- status: Accepted date: 2026-07-17 applyTo: - "Fuchs/code/FuchsPdf.cs" - "Fuchs/Services/FuchsPdfService.cs" - "Fuchs/Services/InvoiceService.cs" - "Fuchs/Services/ERechnungSettings.cs" - "eRechnungLib/**" supersededBy: "" --- # 0012 — eRechnung uses a single PDF/A engine (eRechnungLib owns PDF/A-3) ## Context ADR 0005 established that invoices are emitted as eRechnung by embedding the CII XML into the FuchsPdf-rendered visual PDF via `eRechnungLib.ToZugferd(...)`. Two hard requirements then surfaced: the emitted invoice must (a) satisfy the **ZUGFeRD 2.4 / Factur-X** standard for **DATEV** ingestion, and (b) be a **formally verifiable PDF/A-3** (veraPDF-clean). A conflict became apparent in the rendering pipeline. `FuchsPdf.DocToPdfBytes` post-processes its MigraDoc/PdfSharp output to **PDF/A via Spire** (`OCORE…pdfAFileContent`). `eRechnungLib`'s `FacturXPdfBuilder` **also** produces a PDF/A layer (raises to PDF 1.7, writes `pdfaid` XMP, adds an sRGB output intent, embeds `factur-x.xml` in `/AF`). Feeding a Spire-made PDF/A into eRechnungLib stacks **two** PDF/A conversions → duplicate/*conflicting* output intents and `pdfaid` markers, which veraPDF rejects. Spire's output is also PDF/A-1/2 and does **not** carry the `/AF` associated-file structure ZUGFeRD requires (PDF/A-3). Separately, `eRechnungLib` shipped **no** sRGB ICC profile, so its output intent was silently omitted (`PDFA-ICC` warning) — never formally PDF/A-3 conformant. ## Decision - **eRechnungLib is the single PDF/A engine for eRechnung output.** The invoice visual PDF is rendered by `FuchsPdf` **without** the Spire PDF/A step and handed to `eRechnungLib.ToZugferd(ZugferdProfile.EN16931, rawPdfBytes)`, which owns the one PDF/A-3 conversion and embeds the CII XML. The render-only path is `FuchsPdf.DocToPdfBytesRaw` / `IPdfService.DocToPdfBytesRaw` (fonts still embedded via `OCOREFontResolver`, no PDF/A post-processing). - **Spire stays only for on-screen preview rasterisation** (`DocToImageCollection` / `BytesToImageCollection` for `sprep`/`sedit`). It is **not** part of the eRechnung file's PDF/A path. `DocToPdfBytes` (render + Spire PDF/A) is unchanged and remains the path for non-eRechnung documents (e.g. reminders). - **A bundled sRGB ICC profile is required.** `eRechnungLib` ships `Resources/Color/sRGB.icc` (sRGB IEC61966-2.1) so the PDF/A output intent is always attached. A caller may override it per conversion via `ConversionOptions.IccProfile`. - **Profile is EN 16931.** MINIMUM / BASIC WL are not offered for real invoices — DATEV needs at least EN 16931 (COMFORT) for full booking. - **Formal conformance is verified by an external online service** (veraPDF for PDF/A-3 + a ZUGFeRD/EN 16931 validator), behind the configurable `Fuchs:ERechnung:Validation:ServiceUrl` seam. Until the URL is provisioned, verification reports "not configured / skipped". ## Consequences - The eRechnung invoice PDF and a plain Spire PDF/A must never both be produced for the same document — pick the render-only path when emitting eRechnung. - The incoming visual PDF must itself be PDF/A-friendly (fonts embedded — handled; letterhead images must be **RGB, not CMYK**; transparency is allowed because we target PDF/A-**3**). - `Fuchs:ERechnung:Enabled` gates emission and stays `false` until the `FdsInvoiceData` → `eRechnungLib.Model.Invoice` mapping is wired (the ADR 0005 follow-up). Open item for that mapping: the buyer address is currently a free-text block (`SendToAddress`); EN 16931 needs **structured** buyer fields (name/postcode/city/country, VAT id), so structured customer master data must feed the mapping. Seller data (currently hard-coded in `FuchsPdf`: name, address, tax number, IBAN/BIC) must be lifted into the seller model. - `Fuchs.csproj` must add a project reference to `eRechnungLib` when the flow is wired (not present yet). ## Alternatives considered - **Keep Spire PDF/A and have eRechnungLib only embed the XML:** rejected — Spire produces the wrong PDF/A part (1/2, no `/AF`) and a second conversion collides with eRechnungLib's own output intent/XMP, failing veraPDF. - **Drop Spire entirely:** rejected — Spire is still needed to rasterise PDFs to the on-screen invoice/reminder preview images; PdfSharp/eRechnungLib cannot. - **Ship no ICC and rely on callers:** rejected — formal PDF/A-3 requires an output intent; bundling a profile makes conformance the default.