Kulcare Docs
DeveloperHospital surgery center

PDF-First Lab Readiness

Evidence links, clinical review, access, retries, and OT gates for Hospital Lab reports.

Delivery Boundary

U4 extends the U3 private-document foundation in draft PR 2746. The candidate connects the Lab workqueue, report upload, evidence links, review history, and current-source readiness. It supports a disconnected Lab that provides PDF reports. It does not connect a LIS or PACS. It does not create a final diagnostic report, fulfill a Lab order, or publish files to a patient.

Implementation, automated verification, deployment, manual QA, and clinical acceptance are separate states. D2 still blocks staging and production deployment until private storage, scanning, retention, and deletion are accepted. D3 still blocks clinical activation until the clinical owner approves the policy, report timestamp, freshness, and active-case handoff. A local synthetic scanner result is not either approval.

Ownership And Patterns

Clinical owns Hospital::LabEvidence and the readiness command boundary. U3 owns canonical Clinical::Document metadata, private bytes, revisions, and scan state. Hospital consumes these services through hospitalLabApi and hospitalDocumentsApi. The shell owns effective permissions. Admin owns app flags. Neither editor is duplicated in Hospital.

Current comparables are the U2 readiness commands, U3 document consumer, and case-stock retry store. The new evidence table holds immutable provenance, not a second file store or command ledger.

Access And Scope

All paths require authenticated scope and their resource policy. The new Lab queue/history/command policy also checks the app flag and the cases and labReadiness modules. Existing U3 document routes keep their category-authority policy; the new queue grant does not replace it.

OperationRequired permissions beyond membership and facility access
Queueview_hospital, view_surgical_cases, view_lab_readiness
Evidence and command historyQueue grants plus manage_lab_readiness
Link, invalidate, reviewHistory grants, active tenant, manual Lab mode, nonterminal case, current policy and versions
Private document metadata and bytesExisting U3 Lab category authority; queue view does not grant access
Lab mode changeExisting manage_hospital_configuration; current configuration version

view_lab_readiness is a new owner-only default in hospital_lab_readiness at view level. Migration 20261019000002_add_hospital_lab_view_permission.rb, seed, defaults, access table, snapshot, key-behavior map, and policy matrix must agree. Existing Lab managers need the explicit view grant for the new workqueue and commands. Do not infer grants from a job title. Suspension preserves authorized history but blocks new commands.

API Contract

The root is /clinical/facilities/:facility_id.

Method and pathContract
GET /readiness_workqueueRequired category=lab. Optional case_id, state, search, scheduled_from, scheduled_to, page, per_page. Returns items, filtered counts, review-pending count, setup gaps, evaluation time, and standard pagination.
GET /surgical_cases/:case_id/readiness/:item_id/lab_evidencePaginated immutable evidence history with authorized U3 document metadata. No storage key, digest, or public URL.
POST /surgical_cases/:case_id/readiness/:item_id/commandsNarrow attach/invalidate actions plus existing review. Uses operation_key, item version, source_revision, and reason. Attach also needs case_document_id and offset-bearing evidence_at.
GET /surgical_cases/:case_id/readiness/:item_id/commandsPaginated command/review history. Optional exact operation_key reconciles an uncertain outcome. Lab history needs Lab management authority.
Existing /documents resourcesU3 multipart upload, revision history, quarantine, private PDF download, scan retry, and upload-key lookup.
Existing Hospital context/configurationContext adds lab_capability. Configuration accepts versioned integration_settings.lab_mode=manual.

Dates are facility-local calendar bounds: scheduled_from is inclusive and scheduled_to is exclusive. No date filter includes unbooked nonterminal cases. An explicit case filter can show terminal history. The server filters before pagination. Counts use the same authorized filtered set, not the current page. Search terms and document contents must not enter audit metadata. Status, dates, page, case, and selected requirement use URL parameters. Reload and case handoffs retain that context. Free-text search can contain patient names. Keep it in memory, not page URLs, history, or browser storage; reload clears it. Rails filters the exact API search parameter from request/path logs. D2 must also verify proxy and access-log redaction. Rows, counts, and allowed actions use one server evaluation time at an expiry boundary. Search ignores requirements that no longer match the bound policy snapshot.

Evidence And Readiness

Each evidence row binds one item/source revision, exact rule snapshot, report revision, patient registration, actor, reason, and report time. Composite foreign keys enforce tenant, facility, case, patient, category, and predecessor scope. FORCE RLS applies to the table. Update and delete are blocked by an immutable-history trigger. Migration 20261019000001_add_hospital_lab_evidence.rb is forward-only to preserve history.

Current sourceReadiness effect
No link, invalidated link, replaced predecessor, or incomplete policyNot started
Pending scanNot started; cannot review or override
Failed transfer or failed scanUnavailable; cannot review or override
Rejected scanBlocked; cannot review or override
Clean, current, fresh report without matching reviewReview pending; not started
Accepted clinical review of that exact revisionReady until its approved expiry
Rejected clinical reviewBlocked
Approved expiry reachedStale in queue, case detail/list, schedule, and the next OT gate

Scan completion never performs clinical review. A replacement registration removes its predecessor's eligibility even if the replacement fails or waits for scan. An independent report does not invalidate unrelated links. The confirmed report timestamp, not upload time, starts the approved validity period. Re-uploading the same dated report does not extend expiry. Ambiguous date-only reports need a clinical decision; the client must not invent midnight or upload time. Correct a wrong link by invalidating it with a reason, then explicitly link the right report and review again.

The Ruby source resolver and SQL projection share these rules. The approved policy requires Lab rules to use the Lab source type. Manual clinical rules do not become Lab evidence or invent a report link. Case-first locks serialize link/review/invalidation, replacement registration, scan finalization, and clinical transitions. Storage transfer and scanning run outside these locks. The implementation does not widen U2 override eligibility to bypass missing, unsafe, stale, or invalidated Lab evidence.

Settings And Retries

manual means PDF-first intake. The backend rejects new unsupported integrated modes. An existing unsupported value remains visible and unavailable until an authorized versioned correction. It is not silently converted to manual mode during an unrelated settings save. History remains readable under its current read policy when intake is unavailable. The module's API badge is separate from upload availability and clinical activation approval.

Upload and binding have separate keys. The client saves hashes and structured retry references in scoped session storage. It does not save PDF bytes, filenames, or clinical reason text there. After an unknown response, look up the original key before a new write. An unconfirmed command needs the original reason after reload; an unfinished upload needs the same file name and bytes. Permission loss or an unavailable lookup must not discard the unresolved operation. A replay is historical confirmation. Refetch current readiness rather than treating its old result as current clearance. Known stale/version failures require reopening against current evidence. Private PDF previews use a Blob URL that is revoked on close or scope change.

Review Decisions

The queue resolves facility-level Lab authority once per request path, not for every row. Current evidence, terminal state, and source eligibility still determine each row's actions. The command endpoint independently checks current authority under its case lock.

Keep a required server PHI audit for every delivered case. Do not deduplicate these records without an approved Audit contract. The client uses TanStack Query's visible-tab polling behavior. Audit capacity must account for a queue page and up to 25 setup-gap cases per read. Private downloads use U3's authorized server audit. There is no hipaaAuditService in the current frontend; do not create a parallel audit path to satisfy an obsolete example.

The two U4 migrations deliberately reject rollback. The backend instructions allow documented forward recovery. This prevents evidence, command history, or tenant permission grants from being lost. Disable intake and use a reviewed forward migration for recovery.

Verification And Release

See manual QA, the U4 plan, and the release record. The release record contains the tested source commit, exact CI counts, both-preset browser coverage, and the pending external review follow-up. Local implementation and HTTP integration are complete. Deployment, manual acceptance, and D2/D3 approval are not complete. Use an owned disposable database for local tests. Never reset a shared development or staging database. Keep the issue open for QA. Do not use a synthetic policy reference as D3 approval.

On this page