# Wundklar · reports

The PDF/A-2b model, on-device preview, encrypted upload and the KIM, print and link delivery paths.

A Wundklar report is a doctor-facing document that drives the next
prescription. The engine renders PDF/A-2b in JavaScript so the device and
the Worker share it (device for the preview, Worker for the server-built
variant and the KIM attachment). Decision:
[ADR-0023](/docs/adr/0023-pdf-a-2b-in-js-shared-by-device-and-worker);
code:
[`packages/report`](https://github.com/CarlosZiegler/wundklare/blob/main/packages/report/package.json)
and
[`packages/api/src/features/reports`](https://github.com/CarlosZiegler/wundklare/blob/main/packages/api/src/features/reports/reports.service.ts).

## Content [#content]

- Service, patient (pseudonymised for network recipients), wound id, body
  site (DE), **allergies in red**, area curve + table, 2 crop photos on the
  same marker scale, today's T.I.M.E. / pain / infection, the active plan
  version, the follow-up request (HKP 31 / 31a), the "Werte manuell mit
  Lineal gemessen von …" footnote, the signer and time, and the SHA-256 of
  the canonical model.
- Reports to doctors are always German regardless of the UI language
  ([ADR-0027](/docs/adr/0027-languages-de-en-pt)).
- The copy guard
  [`packages/clinical`](https://github.com/CarlosZiegler/wundklare/blob/main/packages/clinical/package.json)
  rejects interpretive words ("besser", "schlechter", "improved", …)
  outside the exact approved disclaimers (RN-07, MDR Rule 11).

## On the device [#on-the-device]

`M-RepChoose` picks a template, `M-RepPreview` renders the PDF/A locally
with the device variant of
[`buildRepresentativeReport`](https://github.com/CarlosZiegler/wundklare/blob/main/packages/report/package.json)
and encrypts the bytes under a fresh per-object DEK wrapped by the ODK
([ADR-0017](/docs/adr/0017-client-side-envelope-encryption-and-key-hierarchy)).
The upload goes through the staged-object pattern
([ADR-0025](/docs/adr/0025-opaque-object-keys-and-staged-clinical-objects))
and `report.create` attaches it inside the mutation transaction.

## Delivery [#delivery]

`M-RepSend` offers three paths:

- **KIM** — the fastest, routed through the service's own client module
  ([ADR-0024](/docs/adr/0024-kim-through-the-services-own-client-module)).
  Per-Organization credentials are KEK-wrapped; `KIM_TRANSPORT=fake`
  routes to `/dev/kim-inbox` for walkthroughs; `KIM_TRANSPORT=smtp` sends
  through the service's STARTTLS 587 bridge. `reports.deliver` writes the
  outbox row; `reportsKim` leases and sends; delivery events feed the
  trail and the `report_no_reply` reminder (+2 days).
- **Print** — the device renders the PDF in memory, the nurse hands it
  over. Nothing is persisted beyond the report row.
- **Link** — the device creates a
  [share link](/docs/features/wundklar-share-links) from its link vault.

## Server-built reports [#server-built-reports]

Automated follow-up requests (expiring prescriptions, rule-of-thumb
consults) are built on the Worker by `reportsGenerate` from the same model;
server-side decryption is logged under a named system reason and runs only
in the job
([ADR-0028](/docs/adr/0028-immutable-clinical-records-and-privilege-matrix)).

## Verification [#verification]

veraPDF is mandatory: `docker run --rm -v "$PWD/<dir>:/data" verapdf/cli --flavour 2b /data/<file>.pdf`
gates the Node and Worker outputs in CI and the Expo-web bench; a non-2b
output blocks the merge.

