Overview
High-level picture of how PDF lab reports are handled when labs choose to upload a finished document rather than manually inputting values into the system
Overview
Overview
This guide is written for engineers to read and learn about the File Type Report Revamp: why it exists, how it differs from the legacy server-mediated upload path, what the observed livehealth-frontend + livehealthapp (PY-2) happy path does today, and where PY-3 + Lambda-facing surfaces extend the architecture without necessarily being the only production path visible in a given repo snapshot.
Use the sibling pages for depth:
- Workflow Guide - step-by-step lifecycle, setup, verification, failure modes
- Frontend - React entry points, helpers, presigned orchestration
- Backend - PY-2 finalization, Storage Manager, PY-3 helpers, persistence and indexing
- Design Decisions - tradeoffs, dual paths, caveats
Prerequisites
| Requirement | Why it matters |
|---|---|
User with allow_report_file_conversion (or API-allowed doctor access) | Without it, convert-to-file is blocked in operations. |
| Report not radiology | Conversion / upload paths reject radiology in PY-2 guards. |
S3 + Storage Manager mapping for FileTypeReport | Presigned generation needs account, bucket, region, and extension allowlist. |
| PY-2 routes reachable from the browser | sm_generate_presigned_url/, sm_reconcile_presigned_url/, uploadFileTypeReport/, convertReportToFileOrNormal/. |
| Pusher + patient-report Elasticsearch healthy | Completion is persisted even if UI looks stale when realtime/indexing fails. |
| Optional Lambda path | S3 events, deployed Lambda, X-Lambda-Token / CRON_SIGNING_KEY, and PY-3 file-type endpoints, only if that deployment shape is used. |
What Is It For
- Product: Let a lab attach a finished report file (PDF or supported image) as the analytical result instead of typing every parameter.
- Operations: Reduce friction for high-volume reporting where the authoritative artifact already exists outside the LIS parameter grid.
- Engineering: Remove the application server from the binary upload path on the default flow so large multi-page PDFs are practical, while keeping domain finalization (report row, audit, search, realtime) on trusted backend code.
Key Features
| Topic | Summary |
|---|---|
| What is a file type report? | A report where the system stores a file path (typically PDF or image) instead of manually entered parameter values. |
| Why was the revamp needed? | The old architecture pushed the entire file payload through the backend, creating payload-size and performance bottlenecks for larger lab reports. |
| What changed? | The new architecture uses Storage Manager presigned upload URLs so the browser uploads directly to object storage instead of sending the raw file through the application backend on the main path. |
| Biggest practical gain | File transfer is offloaded from the app server, reducing request pressure and earlier size restrictions tied to backend payload transport. |
| Core business effect | Labs can attach a finished report document instead of keying every value manually. |
| Important nuance from code | The current livehealth-frontend happy path definitely uses presigned upload plus PY-2 finalization. The repository also contains PY-3 Lambda-facing endpoints for a more decoupled path; Lambda source is not in the inspected repo snapshot. |
| Another important nuance | The βApply header and footerβ flow still uses the legacy server-mediated upload path and does not use the presigned upload flow. |
Glossary
| Term | Meaning in this system | Typical place seen in code |
|---|---|---|
| File Type Report | A report whose result is a file attachment path rather than traditional report parameter values. | fileInputReport, ReportValue.value |
fileInputReport | Flag on labReportRelation / LabReportRelation indicating file-based report behavior. | PY-2 labs/API.py, PY-3 report/models/lab_report_relation.py |
| Report Value | DB row storing the effective value for a report parameter; for file reports, value is the file path. | PY-2 save_file_type_report_to_report_value, PY-3 update_lab_report_and_report_value_with_path |
| Storage Manager | Shared file-storage abstraction: paths, presigned URLs, metadata logs, cleanup, download/reconcile. | PY-2 labs/storage_manager.py, PY-3 core/utils/storage_manager/* |
| Presigned URL | Short-lived direct-upload contract from backend so the client uploads straight to S3. | sm_generate_presigned_url, storage-manager generate-presigned-url |
| Reconcile | Post-upload step verifying the object exists and updating Storage Manager logs with final size / status. | sm_reconcile_presigned_url, presigned reconcile |
| Temporary path | Caller-specified path before canonical Storage Manager placement. | FileTypeReports/... prefix patterns |
| Concrete path | Canonical Storage Manager path matching standard SM conventions. | IN/<lab>/<patient>/FileTypeReport/<cloudDocId>_<filename>.pdf style paths |
| Pusher update | Real-time report / waiting-list refresh after upload or finalization. | commonPusherFunctionForLabReportRelation |
| ES | Elasticsearch - patient/report search indexing and Storage Manager log records. | LabReportRelationES, StorageManagerLog |
What problem the revamp solves
Old behavior
Under the older mechanism, file type reports were uploaded via the backend store path:
- the browser read the file
- the raw payload moved through the application request
- the backend validated and stored the file
- only then was the report updated
Predictable pain points:
- large request bodies
- backend CPU and memory pressure
- poor scaling for high-resolution and multi-page PDFs
- stricter effective file-size limits because the application server sat in the middle of the upload stream
New behavior
The revamp shifts bulk transfer out of the application tier:
- the frontend asks for a presigned upload contract
- the backend generates an S3 target and logs the request
- the frontend uploads directly to S3
- the system then reconciles metadata and finalizes the report record
Architecture-level impact
| Area | Old model | New model |
|---|---|---|
| Raw file transport | Browser β Backend β Storage | Browser β Storage |
| App-server involvement during upload | High | Low |
| Payload bottleneck on app server | Yes | Largely removed |
| File-size tolerance | Constrained by backend transport | Much better when S3 receives the binary directly |
| Post-upload bookkeeping | Backend only | Split across frontend metadata calls, Storage Manager logs, report finalization |
| Extensibility | Tight coupling | Better decoupling when Lambda / PY-3 helpers are used |
Reality check from the codebase
The architecture described in product/technical context and the architecture visible in source code are closely related, but not one single linear path in every deployment.
What is definitely live in the current frontend code
The current livehealth-frontend upload flow does this:
- Validate the selected file.
- Request a presigned upload from PY-2
sm_generate_presigned_url/. - Upload the binary to S3 directly.
- Reconcile via
sm_reconcile_presigned_url/. - Call PY-2
uploadFileTypeReport/with metadata only, especiallyinitialFilePath. - Let PY-2 update the report value, send Pusher updates, and re-index the report in ES.
What also exists in the repository
Broader Lambda / PY-3 support surfaces:
- PY-3 Storage Manager APIs
- Lambda auth via
X-Lambda-Token - PY-3 endpoint to convert a temporary file path into a concrete Storage Manager path
- PY-3 endpoint to update the report value with the final file path
- the presigned-upload revamp is implemented in the FE + PY-2 path
- the PY-3 / Lambda support surfaces are present in
crelio-app - the exact production Lambda implementation is external to this repo snapshot or lives in another repo / deployment artifact
Cross-repo map (repositories and ownership)
| Repo / app | Layer | Why it matters for this revamp |
|---|---|---|
livehealth-frontend | Browser UI and orchestration | Starts upload, requests presigned URL, uploads to S3, reconciles, triggers report finalization |
livehealthapp | PY-2 operational backend | Owns the currently observed finalization endpoint, report conversion, Pusher trigger, patient-report ES re-index |
crelio-app | PY-3 services and newer Storage Manager stack | Modern Storage Manager endpoints, canonical path utilities, Lambda auth, file-type-report Lambda-facing helpers |
Suggested mental model (Level 0)
- Product meaning - the report result is a file, not typed values.
- State meaning -
fileInputReport = 1;ReportValue.valuestores a path. - Upload meaning - Storage Manager gives the browser a direct lane into S3.
- Domain finalization meaning - backend still decides when the report becomes complete and searchable.
- Infra-assisted evolution - PY-3 and Lambda support preprocessing and path normalization more decoupled than the older PY-2-only synchronous path.
The technical essence: storage-transport decoupling with report-state side effects still owned by the domain layer. See Design Decisions for explicit tradeoffs and caveats.