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;
code:
packages/report
and
packages/api/src/features/reports.
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).
- The copy guard
packages/clinicalrejects interpretive words ("besser", "schlechter", "improved", …) outside the exact approved disclaimers (RN-07, MDR Rule 11).
On the device
M-RepChoose picks a template, M-RepPreview renders the PDF/A locally
with the device variant of
buildRepresentativeReport
and encrypts the bytes under a fresh per-object DEK wrapped by the ODK
(ADR-0017).
The upload goes through the staged-object pattern
(ADR-0025)
and report.create attaches it inside the mutation transaction.
Delivery
M-RepSend offers three paths:
- KIM — the fastest, routed through the service's own client module
(ADR-0024).
Per-Organization credentials are KEK-wrapped;
KIM_TRANSPORT=fakeroutes to/dev/kim-inboxfor walkthroughs;KIM_TRANSPORT=smtpsends through the service's STARTTLS 587 bridge.reports.deliverwrites the outbox row;reportsKimleases and sends; delivery events feed the trail and thereport_no_replyreminder (+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 from its link vault.
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).
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.