chore: update readme and prd
This commit is contained in:
+104
-56
@@ -1,5 +1,29 @@
|
||||
# PRD: VigilCare Records — Paper Chart Digitization & Approval Platform
|
||||
|
||||
## Implementation Status
|
||||
|
||||
**Phases 1–8 are complete.** Phase 9 is partially complete.
|
||||
|
||||
| Phase | Scope | Status |
|
||||
|---|---|---|
|
||||
| 1 | Schema, auth, roles, batch CRUD, MinIO upload, status machine | Done |
|
||||
| 2 | Draft entry API, plausibility validation, submit-for-verification | Done |
|
||||
| 3 | Verification, rejection, separation of duties, work queues | Done |
|
||||
| 4 | Promotion to VigilCareClinical live tables, outbox, idempotency | Done |
|
||||
| 5 | Corrections / supersession, patient digitization history | Done |
|
||||
| 6 | Track B live capture with clinician attestation | Done |
|
||||
| 7 | Digitization workstation UI (`vigilcare-records-web`) | Done |
|
||||
| 8 | Prometheus metrics, supervisor overview, batch events API, promotion retry | Done |
|
||||
| 9 | E2E verification script, clinical scenario docs, extended seed data | Partial |
|
||||
|
||||
**Delivered in Phase 9 so far:** `scripts/run-vigilcare-records-verification-p9.sh` (full workflow + metrics smoke test), [digitization-workstation-guide.md](digitization-workstation-guide.md) (backfill, live capture, corrections).
|
||||
|
||||
**Remaining in Phase 9:** Extended `DataSeeder` with demo patients and batches across all statuses/types/tracks for dashboard demos without manual data entry.
|
||||
|
||||
See [README.md](../README.md) for API reference, quick start, and verification scripts.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
A clinical records intake system that converts paper-based patient charts into structured, human-verified digital records before they enter the VigilCareClinical alerting pipeline. Designed for small hospitals, district clinics, and island health systems where the majority of historical and day-to-day records still exist on paper.
|
||||
@@ -14,7 +38,7 @@ VigilCareClinical ([vigilcare-clinical-api-prd.md](vigilcare-clinical-api-prd.md
|
||||
|
||||
This project maps to `sd-mid-009` (Outbox Pattern for approval promotion events), `sd-mid-013` (CQRS — draft vs live read models), `sd-junior-004` (RBAC), and senior trade-off conversations around **data quality gates vs time-to-value** in resource-constrained health systems.
|
||||
|
||||
**Stack:** .NET 8 Web API, PostgreSQL, MinIO (scanned document storage), Redis (work-queue assignment locks), Serilog → Seq, Prometheus → Grafana, xUnit, Docker Compose. Vue 3 digitization workstation UI (separate repo or `VigilCare.Records.Web` project).
|
||||
**Stack:** .NET 8 Web API, PostgreSQL 16, MinIO (scanned document storage), Redis 7 (batch assignment locks and live-capture threshold cache), Serilog → Seq, Prometheus → Grafana, xUnit, Docker Compose. Vue 3 digitization workstation UI in `vigilcare-records-web/` (Vite, Pinia, Tailwind CSS).
|
||||
|
||||
**Prerequisite / companion:** VigilCareClinicalAPI Phases 1–2 minimum (patient, encounter, observation ingest). Full VigilCare value unlocks as approved observations flow into the existing Kafka alert pipeline.
|
||||
|
||||
@@ -300,7 +324,7 @@ This keeps digitization history, patient coverage stats, and Prometheus batch me
|
||||
|
||||
---
|
||||
|
||||
### 1. Document Upload and Batch Creation
|
||||
### 1. Document Upload and Batch Creation — *implemented (Phase 1)*
|
||||
|
||||
**Description:** Intake clerk scans or uploads a paper record. System stores the file in MinIO, computes SHA-256, creates a batch in `uploaded` state, and writes a `DigitizationEvent`.
|
||||
|
||||
@@ -320,7 +344,7 @@ This keeps digitization history, patient coverage stats, and Prometheus batch me
|
||||
|
||||
---
|
||||
|
||||
### 2. Draft Data Entry
|
||||
### 2. Draft Data Entry — *implemented (Phase 2)*
|
||||
|
||||
**Description:** Entry clerk views the scan alongside structured form fields. Saves draft patient updates, encounter context, and observations. Batch moves to `in_entry` on first save.
|
||||
|
||||
@@ -355,7 +379,7 @@ This keeps digitization history, patient coverage stats, and Prometheus batch me
|
||||
|
||||
---
|
||||
|
||||
### 3. Verification and Rejection
|
||||
### 3. Verification and Rejection — *implemented (Phase 3)*
|
||||
|
||||
**Description:** Verifier reviews entry against the scan. Can approve field-by-field or reject the entire batch with a mandatory reason. Verifier cannot be the entry clerk.
|
||||
|
||||
@@ -364,7 +388,7 @@ On verify pass: status → `verified` or `awaiting_clinical_approval` per [site
|
||||
**Endpoints:**
|
||||
- `GET /api/v1/work-queue/verification` — batches in `pending_verification`, sorted by `submittedAt ASC`
|
||||
- `GET /api/v1/work-queue/clinical-approval` — batches in `awaiting_clinical_approval`, sorted by `submittedAt ASC`
|
||||
- `POST /api/v1/digitization-batches/:id/verify` — body: `{ "fieldChecks": [{ "fieldPath": "observations[0].value", "passed": true }], "passed": true }`
|
||||
- `POST /api/v1/digitization-batches/:id/verify` — body: `{ "fieldChecks": [{ "fieldName": "observations[0].value", "status": "ok", "note": null }], "passed": true }`
|
||||
- `POST /api/v1/digitization-batches/:id/reject` — body: `{ "reason": "..." }` → status `rejected`, notifies entry clerk
|
||||
|
||||
Reject is allowed from `pending_verification` (verifier; separation of duties applies) or `awaiting_clinical_approval` (clinical approver; separation of duties does **not** apply — approver may not have been the entry clerk by role design).
|
||||
@@ -373,12 +397,13 @@ Reject is allowed from `pending_verification` (verifier; separation of duties ap
|
||||
|
||||
---
|
||||
|
||||
### 4. Approval and Promotion to VigilCareClinical
|
||||
### 4. Approval and Promotion to VigilCareClinical — *implemented (Phase 4)*
|
||||
|
||||
**Description:** Final approval triggers an atomic promotion: draft records become live Patient / Encounter / Observation rows in VigilCareClinical (same database in integrated deployment, or HTTP calls to VigilCareClinical API in split deployment). Batch status → `promoted`.
|
||||
|
||||
**Endpoints:**
|
||||
- `POST /api/v1/digitization-batches/:id/approve` — requires `verified` or `awaiting_clinical_approval`; restricted to `ClinicalApprover` or `Administrator`; Idempotency-Key supported
|
||||
- `POST /api/v1/digitization-batches/:id/approve` — requires `verified` or `awaiting_clinical_approval`; restricted to `ClinicalApprover` or `Administrator`; `Idempotency-Key` required; returns **202** with `PROMOTION_DEFERRED` on transient failure (batch stays `approved`)
|
||||
- `POST /api/v1/digitization-batches/:id/promote` — manual promotion of an `approved` batch (also used after deferral)
|
||||
- `GET /api/v1/digitization-batches/:id/promotion-result` — live IDs created: `patientId`, `encounterId`, `observationIds[]`
|
||||
|
||||
**Promotion transaction sequence:**
|
||||
@@ -402,7 +427,7 @@ Reject is allowed from `pending_verification` (verifier; separation of duties ap
|
||||
|
||||
---
|
||||
|
||||
### 5. Corrections and Supersession
|
||||
### 5. Corrections and Supersession — *implemented (Phase 5)*
|
||||
|
||||
**Description:** Approved records are not silently edited. A correction creates a new batch with `supersedesBatchId` pointing to the original. Correction goes through the full entry → verify → approve cycle. On promotion, erroneous live observations are marked `superseded` (append-only — not deleted).
|
||||
|
||||
@@ -414,7 +439,7 @@ Reject is allowed from `pending_verification` (verifier; separation of duties ap
|
||||
|
||||
---
|
||||
|
||||
### 6. Live Capture (Track B)
|
||||
### 6. Live Capture (Track B) — *implemented (Phase 6)*
|
||||
|
||||
**Description:** Credentialed clinician enters vitals or labs at point of care on a tablet. No verification queue. Each submission creates an audit `DigitizationBatch` (see [Track B audit model](#track-b-audit-model)), writes draft observations for traceability, and promotes live observations synchronously with full alert evaluation.
|
||||
|
||||
@@ -428,38 +453,46 @@ Reject is allowed from `pending_verification` (verifier; separation of duties ap
|
||||
|
||||
---
|
||||
|
||||
### 7. Patient Registry (Draft and Live)
|
||||
### 7. Patient Registry (Draft and Live) — *partially implemented*
|
||||
|
||||
**Description:** Search and link batches to patients. Support new patient registration through the draft pipeline.
|
||||
**Description:** Search and link batches to patients. New patient registration flows through the draft pipeline on a `patient_registration` batch; there is no standalone draft-patient API in v1.
|
||||
|
||||
**Endpoints:**
|
||||
- `GET /api/v1/patients/search?q=` — search live VigilCareClinical patients by MRN or name
|
||||
- `POST /api/v1/patients/draft` — create draft-only patient (no MRN until approval)
|
||||
**Implemented endpoints:**
|
||||
- `GET /api/v1/patients/search?q=` — search live patients by MRN or name (min 2 characters)
|
||||
- `GET /api/v1/patients/:id/digitization-history` — all batches for a patient with correction chain and audit trails
|
||||
|
||||
**Deferred (not in v1):**
|
||||
- `POST /api/v1/patients/draft` — create draft-only patient without a batch
|
||||
- `GET /api/v1/patients/:id/summary` — live patient + pending draft batches + digitization coverage stats
|
||||
|
||||
**Digitization coverage stat:** `approvedBatchCount / estimatedTotalBatches` — optional manual `estimatedChartSections` per patient for progress tracking.
|
||||
**Digitization coverage stat (future):** `approvedBatchCount / estimatedTotalBatches` — optional manual `estimatedChartSections` per patient for progress tracking.
|
||||
|
||||
---
|
||||
|
||||
### 8. Work Queues and Operational Dashboard
|
||||
### 8. Work Queues and Operational Dashboard — *implemented (Phase 8)*
|
||||
|
||||
**Description:** Supervisors monitor backlog, assignment, and throughput.
|
||||
|
||||
**Endpoints:**
|
||||
- `GET /api/v1/work-queue/entry` — batches awaiting or in entry
|
||||
- `GET /api/v1/work-queue/clinical-approval` — batches awaiting physician sign-off after verification
|
||||
- `GET /api/v1/work-queue/overview` — counts by status, average time-in-queue, reject rate
|
||||
- `GET /api/v1/digitization-batches/:id/events` — cursor-paginated audit trail
|
||||
- `GET /api/v1/work-queue/entry` — batches awaiting or in entry (`UPLOADED`, `IN_ENTRY`, `REJECTED`)
|
||||
- `GET /api/v1/work-queue/verification` — batches in `PENDING_VERIFICATION`, sorted by submission time
|
||||
- `GET /api/v1/work-queue/clinical-approval` — batches in `AWAITING_CLINICAL_APPROVAL`
|
||||
- `GET /api/v1/work-queue/overview` — counts by status, average time-in-queue, 24h reject rate, oldest pending verification (administrator only)
|
||||
- `GET /api/v1/digitization-batches/:id/events` — cursor-paginated audit trail with actor username and full name
|
||||
|
||||
**Metrics (Prometheus):**
|
||||
**Promotion retry (Phase 8):** When `POST .../approve` fails due to transient infrastructure errors, the batch stays `APPROVED` and returns **202** with `PROMOTION_DEFERRED`. `PromotionRetryService` retries with exponential backoff; operators may also call `POST .../promote` manually.
|
||||
|
||||
**Metrics (Prometheus) — implemented at `GET /metrics`:**
|
||||
- `digitization_batches_by_status` (gauge)
|
||||
- `digitization_promotion_duration_seconds` (histogram)
|
||||
- `digitization_rejection_total` (counter)
|
||||
- `digitization_queue_age_seconds` (gauge — oldest pending verification)
|
||||
|
||||
Docker Compose exposes Prometheus on port **9095** and Grafana on **3013**.
|
||||
|
||||
---
|
||||
|
||||
### 9. Authentication and Audit
|
||||
### 9. Authentication and Audit — *implemented (Phases 1, 8)*
|
||||
|
||||
**Description:** JWT auth with role claims. Every state transition writes a `DigitizationEvent`. Document access logged.
|
||||
|
||||
@@ -477,18 +510,20 @@ Reject is allowed from `pending_verification` (verifier; separation of duties ap
|
||||
|
||||
---
|
||||
|
||||
## Digitization Workstation UI
|
||||
## Digitization Workstation UI — *implemented (Phase 7)*
|
||||
|
||||
Separate Vue 3 SPA or Razor-hosted frontend. Four primary views:
|
||||
Vue 3 SPA at `vigilcare-records-web/` (dev server port **3028**, proxies `/api` → API on **5217**). Four primary views:
|
||||
|
||||
| View | User | Purpose |
|
||||
|---|---|---|
|
||||
| **Intake** | Intake clerk | Upload, assign patient, print MRN label |
|
||||
| **Entry** | Data entry clerk | Side-by-side scan + form |
|
||||
| **Intake** | Intake clerk | Upload, assign patient, assign entry clerk |
|
||||
| **Entry** | Data entry clerk | Side-by-side scan + form with auto-save |
|
||||
| **Verification** | Verifier | Side-by-side with field checkboxes, approve/reject |
|
||||
| **Queue dashboard** | Supervisor | Backlog, reject rate, clerk throughput |
|
||||
| **Queue dashboard** | Administrator | Backlog metrics from work-queue overview |
|
||||
|
||||
Not a full EMR UI. No clinical alerting views — those remain in VigilCareClinical's ward dashboard.
|
||||
Role-based routing and JWT refresh are implemented. Not a full EMR UI — clinical alerting views remain in VigilCareClinical's ward dashboard.
|
||||
|
||||
See [digitization-workstation-guide.md](digitization-workstation-guide.md) for operator workflows and clinical scenarios.
|
||||
|
||||
---
|
||||
|
||||
@@ -522,38 +557,42 @@ If VigilCareClinical is unreachable in split deployment, batch remains `approved
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
| Criterion | Verification |
|
||||
|---|---|
|
||||
| Separation of duties | Entry clerk cannot verify or approve own batch — `409` |
|
||||
| Draft isolation | Draft observations never appear in VigilCareClinical alert queries or ward dashboard |
|
||||
| Promotion atomicity | Partial promotion (patient created, observations failed) never committed |
|
||||
| Idempotent approval | Duplicate `Idempotency-Key` on approve returns same result, no duplicate observations |
|
||||
| Rejection loop | Rejected batch returns to entry; resubmit reaches verification again |
|
||||
| Backfill alert suppression | Default backfill promotion creates observations with zero alerts |
|
||||
| Live capture alert path | Track B critical potassium triggers synchronous alert in VigilCareClinical |
|
||||
| Audit completeness | Every status transition has a `DigitizationEvent` with actor and timestamp |
|
||||
| Document immutability | Scan object in MinIO not modified or deleted on reject/correct |
|
||||
| Plausibility at draft | Value 520 for potassium rejected at draft save, not at promotion |
|
||||
| Clinical approval routing | `vitals_sheet` verify-pass → `awaiting_clinical_approval` when site config requires it |
|
||||
| Track B audit batch | Live capture creates `DigitizationBatch` in `promoted` with draft observations and events |
|
||||
| Draft assignment guard | Unassigned clerk receives `409 BATCH_NOT_ASSIGNED` on draft save |
|
||||
| Cross-patient duplicate scan | Same SHA for two different patients allowed; same patient within 24h rejected |
|
||||
| Criterion | Verification | Status |
|
||||
|---|---|---|
|
||||
| Separation of duties | Entry clerk cannot verify or approve own batch — `409` | Done |
|
||||
| Draft isolation | Draft observations never appear in VigilCareClinical alert queries or ward dashboard | Done |
|
||||
| Promotion atomicity | Partial promotion (patient created, observations failed) never committed | Done |
|
||||
| Idempotent approval | Duplicate `Idempotency-Key` on approve returns same result, no duplicate observations | Done |
|
||||
| Rejection loop | Rejected batch returns to entry; resubmit reaches verification again | Done |
|
||||
| Backfill alert suppression | Default backfill promotion creates observations with zero alerts | Done |
|
||||
| Live capture alert path | Track B critical potassium triggers synchronous alert in VigilCareClinical | Done |
|
||||
| Audit completeness | Every status transition has a `DigitizationEvent` with actor and timestamp | Done |
|
||||
| Document immutability | Scan object in MinIO not modified or deleted on reject/correct | Done |
|
||||
| Plausibility at draft | Value 520 for potassium rejected at draft save, not at promotion | Done |
|
||||
| Clinical approval routing | `vitals_sheet` verify-pass → `awaiting_clinical_approval` when site config requires it | Done |
|
||||
| Track B audit batch | Live capture creates `DigitizationBatch` in `promoted` with draft observations and events | Done |
|
||||
| Draft assignment guard | Unassigned clerk receives `409 BATCH_NOT_ASSIGNED` on draft save | Done |
|
||||
| Cross-patient duplicate scan | Same SHA for two different patients allowed; same patient within 24h rejected | Done |
|
||||
| Supervisor metrics | Work-queue overview and Prometheus gauges reflect live batch counts | Done |
|
||||
| Promotion retry | Transient promotion failure defers to `APPROVED` with automatic retry | Done |
|
||||
| E2E verification script | `./scripts/run-vigilcare-records-verification-p9.sh` passes against running API | Done |
|
||||
| Extended demo seed data | Startup seed includes patients/batches across all statuses for dashboard demos | Pending |
|
||||
|
||||
---
|
||||
|
||||
## Build Order
|
||||
|
||||
| Phase | Focus |
|
||||
|---|---|
|
||||
| 1 | Schema, auth, roles, batch CRUD, MinIO upload, status machine |
|
||||
| 2 | Draft entry API (patient, encounter, observations), submit-for-verification |
|
||||
| 3 | Verification, rejection, separation of duties, work queues |
|
||||
| 4 | Promotion service → VigilCareClinical live tables, outbox integration, idempotency |
|
||||
| 5 | Corrections / supersession, patient digitization history |
|
||||
| 6 | Track B live capture with clinician attestation |
|
||||
| 7 | Digitization workstation UI (entry + verification side-by-side) |
|
||||
| 8 | Prometheus metrics, supervisor dashboard, promotion retry job |
|
||||
| 9 | Seed data, E2E verification script, clinical scenario documentation |
|
||||
| Phase | Focus | Status |
|
||||
|---|---|---|
|
||||
| 1 | Schema, auth, roles, batch CRUD, MinIO upload, status machine | Done |
|
||||
| 2 | Draft entry API (patient, encounter, observations), submit-for-verification | Done |
|
||||
| 3 | Verification, rejection, separation of duties, work queues | Done |
|
||||
| 4 | Promotion service → VigilCareClinical live tables, outbox integration, idempotency | Done |
|
||||
| 5 | Corrections / supersession, patient digitization history | Done |
|
||||
| 6 | Track B live capture with clinician attestation | Done |
|
||||
| 7 | Digitization workstation UI (entry + verification side-by-side) | Done |
|
||||
| 8 | Prometheus metrics, supervisor dashboard, promotion retry job | Done |
|
||||
| 9 | Extended seed data, E2E verification script, clinical scenario documentation | Partial |
|
||||
|
||||
---
|
||||
|
||||
@@ -634,7 +673,13 @@ This phase connects Records to Clinical. Run against a VigilCareClinical Phase 2
|
||||
|
||||
### Phases 7–9 — UI, Observability, Documentation
|
||||
|
||||
Build the side-by-side workstation UI. Add Prometheus metrics and a supervisor queue view. Write `docs/digitization-workstation-guide.md` and an E2E script `./scripts/run-vigilcare-records-verification.sh`.
|
||||
**Phase 7 (done):** Vue 3 workstation UI with intake, entry, verification, and supervisor dashboard views. Role-based routing, split-pane scan viewer, presigned URL refresh.
|
||||
|
||||
**Phase 8 (done):** Prometheus metrics, `GET /work-queue/overview`, cursor-paginated `GET /digitization-batches/:id/events`, promotion deferral (202) and `PromotionRetryService`, Docker Prometheus/Grafana stack. Verification: `./scripts/run-vigilcare-records-phase-8-verification.sh`.
|
||||
|
||||
**Phase 9 (partial):**
|
||||
- Done: `docs/digitization-workstation-guide.md`, `./scripts/run-vigilcare-records-verification-p9.sh`, project README
|
||||
- Remaining: extend `DataSeeder.cs` with demo patients and batches across all statuses, types, and tracks
|
||||
|
||||
---
|
||||
|
||||
@@ -678,6 +723,9 @@ Build the side-by-side workstation UI. Add Prometheus metrics and a supervisor q
|
||||
|
||||
## References
|
||||
|
||||
- [README.md](../README.md) — API reference, quick start, verification scripts, data models
|
||||
- [digitization-workstation-guide.md](digitization-workstation-guide.md) — clinical scenarios (backfill, live capture, corrections)
|
||||
- [plans/](plans/) — phase-by-phase implementation guides (Phases 1–9)
|
||||
- [vigilcare-clinical-api-prd.md](vigilcare-clinical-api-prd.md) — downstream alerting and observation ingest
|
||||
- [Completed/VigilCareClinicalAPI/VigilCare-Partner-Brief.md](Completed/VigilCareClinicalAPI/VigilCare-Partner-Brief.md) — clinical positioning and scope boundaries
|
||||
- [Completed/national-digital-services-architecture.md](Completed/national-digital-services-architecture.md) — scan-and-verify pattern for paper-to-digital government services
|
||||
|
||||
Reference in New Issue
Block a user